2011-01-31 20:55:26 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/*
|
2012-01-04 16:35:52 +01:00
|
|
|
* Copyright 2012 Facebook, Inc.
|
2011-01-31 20:55:26 +01:00
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
return array(
|
|
|
|
|
|
|
|
// The root URI which Phabricator is installed on.
|
|
|
|
// Example: "http://phabricator.example.com/"
|
|
|
|
'phabricator.base-uri' => null,
|
|
|
|
|
2011-04-04 23:22:16 +02:00
|
|
|
// If you have multiple environments, provide the production environment URI
|
|
|
|
// here so that emails, etc., generated in development/sandbox environments
|
|
|
|
// contain the right links.
|
|
|
|
'phabricator.production-uri' => null,
|
|
|
|
|
2011-05-05 20:00:05 +02:00
|
|
|
// Setting this to 'true' will invoke a special setup mode which helps guide
|
|
|
|
// you through setting up Phabricator.
|
|
|
|
'phabricator.setup' => false,
|
|
|
|
|
2011-02-06 20:53:46 +01:00
|
|
|
// The default PHID for users who haven't uploaded a profile image. It should
|
|
|
|
// be 50x50px.
|
2011-05-02 17:37:56 +02:00
|
|
|
'user.default-profile-image-phid' => 'PHID-FILE-4d61229816cfe6f2b2a3',
|
2011-02-05 20:45:13 +01:00
|
|
|
|
Provide a setting which forces all file views to be served from an alternate
domain
Summary:
See D758, D759.
- Provide a strongly recommended setting which permits configuration of an
alternate domain.
- Lock cookies down better: set them on the exact domain, and use SSL-only if
the configuration is HTTPS.
- Prevent Phabriator from setting cookies on other domains.
This assumes D759 will land, it is not effective without that change.
Test Plan:
- Attempted to login from a different domain and was rejected.
- Logged out, logged back in normally.
- Put install in setup mode and verified it revealed a warning.
- Configured an alterate domain.
- Tried to view an image with an old URI, got a 400.
- Went to /files/ and verified links rendered to the alternate domain.
- Viewed an alternate domain file.
- Tried to view an alternate domain file without the secret key, got a 404.
Reviewers: andrewjcg, erling, aran, tuomaspelkonen, jungejason, codeblock
CC: aran
Differential Revision: 760
2011-08-02 07:24:00 +02:00
|
|
|
// -- IMPORTANT! Security! -------------------------------------------------- //
|
|
|
|
|
|
|
|
// IMPORTANT: By default, Phabricator serves files from the same domain the
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
// application lives on. This is convenient but not secure: it creates a large
|
|
|
|
// class of vulnerabilities which can not be generally mitigated.
|
Provide a setting which forces all file views to be served from an alternate
domain
Summary:
See D758, D759.
- Provide a strongly recommended setting which permits configuration of an
alternate domain.
- Lock cookies down better: set them on the exact domain, and use SSL-only if
the configuration is HTTPS.
- Prevent Phabriator from setting cookies on other domains.
This assumes D759 will land, it is not effective without that change.
Test Plan:
- Attempted to login from a different domain and was rejected.
- Logged out, logged back in normally.
- Put install in setup mode and verified it revealed a warning.
- Configured an alterate domain.
- Tried to view an image with an old URI, got a 400.
- Went to /files/ and verified links rendered to the alternate domain.
- Viewed an alternate domain file.
- Tried to view an alternate domain file without the secret key, got a 404.
Reviewers: andrewjcg, erling, aran, tuomaspelkonen, jungejason, codeblock
CC: aran
Differential Revision: 760
2011-08-02 07:24:00 +02:00
|
|
|
//
|
|
|
|
// To avoid this, you should configure a second domain in the same way you
|
|
|
|
// have the primary domain configured (e.g., point it at the same machine and
|
|
|
|
// set up the same vhost rules) and provide it here. For instance, if your
|
|
|
|
// primary install is on "http://www.phabricator-example.com/", you could
|
|
|
|
// configure "http://www.phabricator-files.com/" and specify the entire
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
// domain (with protocol) here. This will enforce that files are
|
|
|
|
// served only from the alternate domain. Ideally, you should use a
|
|
|
|
// completely separate domain name rather than just a different subdomain.
|
Provide a setting which forces all file views to be served from an alternate
domain
Summary:
See D758, D759.
- Provide a strongly recommended setting which permits configuration of an
alternate domain.
- Lock cookies down better: set them on the exact domain, and use SSL-only if
the configuration is HTTPS.
- Prevent Phabriator from setting cookies on other domains.
This assumes D759 will land, it is not effective without that change.
Test Plan:
- Attempted to login from a different domain and was rejected.
- Logged out, logged back in normally.
- Put install in setup mode and verified it revealed a warning.
- Configured an alterate domain.
- Tried to view an image with an old URI, got a 400.
- Went to /files/ and verified links rendered to the alternate domain.
- Viewed an alternate domain file.
- Tried to view an alternate domain file without the secret key, got a 404.
Reviewers: andrewjcg, erling, aran, tuomaspelkonen, jungejason, codeblock
CC: aran
Differential Revision: 760
2011-08-02 07:24:00 +02:00
|
|
|
//
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
// It is STRONGLY RECOMMENDED that you configure this. Your install is NOT
|
|
|
|
// SECURE unless you do so.
|
Provide a setting which forces all file views to be served from an alternate
domain
Summary:
See D758, D759.
- Provide a strongly recommended setting which permits configuration of an
alternate domain.
- Lock cookies down better: set them on the exact domain, and use SSL-only if
the configuration is HTTPS.
- Prevent Phabriator from setting cookies on other domains.
This assumes D759 will land, it is not effective without that change.
Test Plan:
- Attempted to login from a different domain and was rejected.
- Logged out, logged back in normally.
- Put install in setup mode and verified it revealed a warning.
- Configured an alterate domain.
- Tried to view an image with an old URI, got a 400.
- Went to /files/ and verified links rendered to the alternate domain.
- Viewed an alternate domain file.
- Tried to view an alternate domain file without the secret key, got a 404.
Reviewers: andrewjcg, erling, aran, tuomaspelkonen, jungejason, codeblock
CC: aran
Differential Revision: 760
2011-08-02 07:24:00 +02:00
|
|
|
'security.alternate-file-domain' => null,
|
2011-08-08 00:14:23 +02:00
|
|
|
|
2011-12-18 20:00:39 +01:00
|
|
|
// Default key for HMAC digests where the key is not important (i.e., the
|
|
|
|
// hash itself is secret). You can change this if you want (to any other
|
|
|
|
// string), but doing so will break existing sessions and CSRF tokens.
|
|
|
|
'security.hmac-key' => '[D\t~Y7eNmnQGJ;rnH6aF;m2!vJ8@v8C=Cs:aQS\.Qw',
|
|
|
|
|
|
|
|
|
2011-02-05 20:45:13 +01:00
|
|
|
// -- DarkConsole ----------------------------------------------------------- //
|
|
|
|
|
|
|
|
// DarkConsole is a administrative debugging/profiling tool built into
|
|
|
|
// Phabricator. You can leave it disabled unless you're developing against
|
|
|
|
// Phabricator.
|
2011-02-05 21:20:18 +01:00
|
|
|
|
2011-02-05 20:45:13 +01:00
|
|
|
// Determines whether or not DarkConsole is available. DarkConsole exposes
|
|
|
|
// some data like queries and stack traces, so you should be careful about
|
|
|
|
// turning it on in production (although users can not normally see it, even
|
|
|
|
// if the deployment configuration enables it).
|
2011-05-05 20:00:05 +02:00
|
|
|
'darkconsole.enabled' => false,
|
2011-02-05 21:20:18 +01:00
|
|
|
|
2011-02-05 20:45:13 +01:00
|
|
|
// Always enable DarkConsole, even for logged out users. This potentially
|
|
|
|
// exposes sensitive information to users, so make sure untrusted users can
|
|
|
|
// not access an install running in this mode. You should definitely leave
|
|
|
|
// this off in production. It is only really useful for using DarkConsole
|
2012-01-20 16:39:55 +01:00
|
|
|
// utilities to debug or profile logged-out pages. You must set
|
2011-02-05 20:45:13 +01:00
|
|
|
// 'darkconsole.enabled' to use this option.
|
|
|
|
'darkconsole.always-on' => false,
|
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
|
2011-02-12 01:48:43 +01:00
|
|
|
// Allows you to mask certain configuration values from appearing in the
|
|
|
|
// "Config" tab of DarkConsole.
|
|
|
|
'darkconsole.config-mask' => array(
|
|
|
|
'mysql.pass',
|
|
|
|
'amazon-ses.secret-key',
|
|
|
|
'recaptcha.private-key',
|
|
|
|
'phabricator.csrf-key',
|
|
|
|
'facebook.application-secret',
|
2011-04-30 07:20:52 +02:00
|
|
|
'github.application-secret',
|
2011-02-12 01:48:43 +01:00
|
|
|
),
|
|
|
|
|
2011-08-08 00:14:23 +02:00
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// -- MySQL --------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// The username to use when connecting to MySQL.
|
|
|
|
'mysql.user' => 'root',
|
2011-02-02 00:52:04 +01:00
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// The password to use when connecting to MySQL.
|
|
|
|
'mysql.pass' => '',
|
2011-02-02 00:52:04 +01:00
|
|
|
|
2011-06-08 19:10:11 +02:00
|
|
|
// The MySQL server to connect to. If you want to connect to a different
|
|
|
|
// port than the default (which is 3306), specify it in the hostname
|
|
|
|
// (e.g., db.example.com:1234).
|
2011-02-01 01:50:08 +01:00
|
|
|
'mysql.host' => 'localhost',
|
2011-02-12 01:12:24 +01:00
|
|
|
|
2012-01-20 00:04:38 +01:00
|
|
|
// The number of times to try reconnecting to the MySQL database
|
|
|
|
'mysql.connection-retries' => 3,
|
|
|
|
|
2011-08-08 00:14:23 +02:00
|
|
|
|
2011-02-09 20:11:24 +01:00
|
|
|
// -- Email ----------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Some Phabricator tools send email notifications, e.g. when Differential
|
|
|
|
// revisions are updated or Maniphest tasks are changed. These options allow
|
|
|
|
// you to configure how email is delivered.
|
2011-02-12 01:12:24 +01:00
|
|
|
|
2011-02-09 20:11:24 +01:00
|
|
|
// You can test your mail setup by going to "MetaMTA" in the web interface,
|
2011-02-12 01:12:24 +01:00
|
|
|
// clicking "Send New Message", and then composing a message.
|
2011-02-09 20:11:24 +01:00
|
|
|
|
|
|
|
// Default address to send mail "From".
|
|
|
|
'metamta.default-address' => 'noreply@example.com',
|
2011-02-12 01:12:24 +01:00
|
|
|
|
2011-04-10 17:46:17 +02:00
|
|
|
// Domain used to generate Message-IDs.
|
|
|
|
'metamta.domain' => 'example.com',
|
|
|
|
|
2011-02-09 20:11:24 +01:00
|
|
|
// When a user takes an action which generates an email notification (like
|
|
|
|
// commenting on a Differential revision), Phabricator can either send that
|
|
|
|
// mail "From" the user's email address (like "alincoln@logcabin.com") or
|
|
|
|
// "From" the 'metamta.default-address' address. The user experience is
|
|
|
|
// generally better if Phabricator uses the user's real address as the "From"
|
|
|
|
// since the messages are easier to organize when they appear in mail clients,
|
|
|
|
// but this will only work if the server is authorized to send email on behalf
|
|
|
|
// of the "From" domain. Practically, this means:
|
|
|
|
// - If you are doing an install for Example Corp and all the users will
|
|
|
|
// have corporate @corp.example.com addresses and any hosts Phabricator
|
|
|
|
// is running on are authorized to send email from corp.example.com,
|
|
|
|
// you can enable this to make the user experience a little better.
|
|
|
|
// - If you are doing an install for an open source project and your
|
|
|
|
// users will be registering via Facebook and using personal email
|
|
|
|
// addresses, you MUST NOT enable this or virtually all of your outgoing
|
|
|
|
// email will vanish into SFP blackholes.
|
|
|
|
// - If your install is anything else, you're much safer leaving this
|
|
|
|
// off since the risk in turning it on is that your outgoing mail will
|
|
|
|
// mostly never arrive.
|
|
|
|
'metamta.can-send-as-user' => false,
|
|
|
|
|
|
|
|
// Adapter class to use to transmit mail to the MTA. The default uses
|
2011-05-12 17:15:02 +02:00
|
|
|
// PHPMailerLite, which will invoke "sendmail". This is appropriate
|
|
|
|
// if sendmail actually works on your host, but if you haven't configured mail
|
2011-02-09 20:11:24 +01:00
|
|
|
// it may not be so great. You can also use Amazon SES, by changing this to
|
|
|
|
// 'PhabricatorMailImplementationAmazonSESAdapter', signing up for SES, and
|
|
|
|
// filling in your 'amazon-ses.access-key' and 'amazon-ses.secret-key' below.
|
|
|
|
'metamta.mail-adapter' =>
|
|
|
|
'PhabricatorMailImplementationPHPMailerLiteAdapter',
|
|
|
|
|
|
|
|
// When email is sent, try to hand it off to the MTA immediately. This may
|
|
|
|
// be worth disabling if your MTA infrastructure is slow or unreliable. If you
|
|
|
|
// disable this option, you must run the 'metamta_mta.php' daemon or mail
|
|
|
|
// won't be handed off to the MTA. If you're using Amazon SES it can be a
|
|
|
|
// little slugish sometimes so it may be worth disabling this and moving to
|
|
|
|
// the daemon after you've got your install up and running. If you have a
|
|
|
|
// properly configured local MTA it should not be necessary to disable this.
|
|
|
|
'metamta.send-immediately' => true,
|
|
|
|
|
|
|
|
// If you're using Amazon SES to send email, provide your AWS access key
|
|
|
|
// and AWS secret key here. To set up Amazon SES with Phabricator, you need
|
|
|
|
// to:
|
|
|
|
// - Make sure 'metamta.mail-adapter' is set to:
|
|
|
|
// "PhabricatorMailImplementationAmazonSESAdapter"
|
|
|
|
// - Make sure 'metamta.can-send-as-user' is false.
|
|
|
|
// - Make sure 'metamta.default-address' is configured to something sensible.
|
|
|
|
// - Make sure 'metamta.default-address' is a validated SES "From" address.
|
|
|
|
'amazon-ses.access-key' => null,
|
|
|
|
'amazon-ses.secret-key' => null,
|
2011-02-01 01:50:08 +01:00
|
|
|
|
2011-05-26 19:00:26 +02:00
|
|
|
// If you're using Sendgrid to send email, provide your access credentials
|
|
|
|
// here. This will use the REST API. You can also use Sendgrid as a normal
|
|
|
|
// SMTP service.
|
|
|
|
'sendgrid.api-user' => null,
|
|
|
|
'sendgrid.api-key' => null,
|
|
|
|
|
2011-05-10 01:31:26 +02:00
|
|
|
// You can configure a reply handler domain so that email sent from Maniphest
|
|
|
|
// will have a special "Reply To" address like "T123+82+af19f@example.com"
|
|
|
|
// that allows recipients to reply by email and interact with tasks. For
|
|
|
|
// instructions on configurating reply handlers, see the article
|
|
|
|
// "Configuring Inbound Email" in the Phabricator documentation. By default,
|
|
|
|
// this is set to 'null' and Phabricator will use a generic 'noreply@' address
|
|
|
|
// or the address of the acting user instead of a special reply handler
|
|
|
|
// address (see 'metamta.default-address'). If you set a domain here,
|
|
|
|
// Phabricator will begin generating private reply handler addresses. See
|
|
|
|
// also 'metamta.maniphest.reply-handler' to further configure behavior.
|
|
|
|
// This key should be set to the domain part after the @, like "example.com".
|
|
|
|
'metamta.maniphest.reply-handler-domain' => null,
|
|
|
|
|
|
|
|
// You can follow the instructions in "Configuring Inbound Email" in the
|
|
|
|
// Phabricator documentation and set 'metamta.maniphest.reply-handler-domain'
|
|
|
|
// to support updating Maniphest tasks by email. If you want more advanced
|
|
|
|
// customization than this provides, you can override the reply handler
|
|
|
|
// class with an implementation of your own. This will allow you to do things
|
|
|
|
// like have a single public reply handler or change how private reply
|
|
|
|
// handlers are generated and validated.
|
|
|
|
// This key should be set to a loadable subclass of
|
|
|
|
// PhabricatorMailReplyHandler (and possibly of ManiphestReplyHandler).
|
|
|
|
'metamta.maniphest.reply-handler' => 'ManiphestReplyHandler',
|
|
|
|
|
2011-08-16 11:31:51 +02:00
|
|
|
// If you don't want phabricator to take up an entire domain
|
|
|
|
// (or subdomain for that matter), you can use this and set a common
|
|
|
|
// prefix for mail sent by phabricator. It will make use of the fact that
|
|
|
|
// a mail-address such as phabricator+D123+1hjk213h@example.com will be
|
|
|
|
// delivered to the phabricator users mailbox.
|
|
|
|
// Set this to the left part of the email address and it well get
|
|
|
|
// prepended to all outgoing mail. If you want to use e.g.
|
|
|
|
// 'phabricator@example.com' this should be set to 'phabricator'.
|
|
|
|
'metamta.single-reply-handler-prefix' => null,
|
|
|
|
|
2011-05-17 00:54:41 +02:00
|
|
|
// Prefix prepended to mail sent by Maniphest. You can change this to
|
|
|
|
// distinguish between testing and development installs, for example.
|
|
|
|
'metamta.maniphest.subject-prefix' => '[Maniphest]',
|
|
|
|
|
2011-05-10 01:31:26 +02:00
|
|
|
// See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
|
|
|
|
// but allows email replies via Differential.
|
|
|
|
'metamta.differential.reply-handler-domain' => null,
|
|
|
|
|
|
|
|
// See 'metamta.maniphest.reply-handler'. This does the same thing, but
|
|
|
|
// affects Differential.
|
|
|
|
'metamta.differential.reply-handler' => 'DifferentialReplyHandler',
|
|
|
|
|
2011-05-17 00:54:41 +02:00
|
|
|
// Prefix prepended to mail sent by Differential.
|
|
|
|
'metamta.differential.subject-prefix' => '[Differential]',
|
|
|
|
|
2011-10-14 21:08:31 +02:00
|
|
|
// Set this to true if you want patches to be attached to mail from
|
|
|
|
// Differential. This won't work if you are using SendGrid as your mail
|
|
|
|
// adapter.
|
|
|
|
'metamta.differential.attach-patches' => false,
|
|
|
|
|
Allow Phabricator to be configured to use a public Reply-To address
Summary:
We already support this (and Facebook uses it) but it is difficult to configure
and you have to write a bunch of code. Instead, provide a simple flag.
See the documentation changes for details, but when this flag is enabled we send
one email with a reply-to like "D2+public+23hf91fh19fh@phabricator.example.com".
Anyone can reply to this, and we figure out who they are based on their "From"
address instead of a unique hash. This is less secure, but a reasonable tradeoff
in many cases.
This also has the advantage over a naive implementation of at least doing object
hash validation.
@jungejason: I don't think this affects Facebook's implementation but this is an
area where we've had problems in the past, so watch out for it when you deploy.
Also note that you must set "metamta.public-replies" to true since Maniphest now
looks for that key specifically before going into public reply mode; it no
longer just tests for a public reply address being generateable (since it can
always generate one now).
Test Plan:
Swapped my local install in and out of public reply mode and commented on
objects. Got expected email behavior. Replied to public and private email
addresses.
Attacked public addresses by using them when the install was configured to
disallow them and by altering the hash and the from address. All this stuff was
rejected.
Reviewed By: jungejason
Reviewers: moskov, jungejason, tuomaspelkonen, aran
CC: aran, epriestley, moskov, jungejason
Differential Revision: 563
2011-06-30 22:01:35 +02:00
|
|
|
// By default, Phabricator generates unique reply-to addresses and sends a
|
|
|
|
// separate email to each recipient when you enable reply handling. This is
|
|
|
|
// more secure than using "From" to establish user identity, but can mean
|
|
|
|
// users may receive multiple emails when they are on mailing lists. Instead,
|
|
|
|
// you can use a single, non-unique reply to address and authenticate users
|
|
|
|
// based on the "From" address by setting this to 'true'. This trades away
|
|
|
|
// a little bit of security for convenience, but it's reasonable in many
|
|
|
|
// installs. Object interactions are still protected using hashes in the
|
|
|
|
// single public email address, so objects can not be replied to blindly.
|
|
|
|
'metamta.public-replies' => false,
|
|
|
|
|
2011-07-04 18:45:42 +02:00
|
|
|
// You can configure an email address like "bugs@phabricator.example.com"
|
|
|
|
// which will automatically create Maniphest tasks when users send email
|
|
|
|
// to it. This relies on the "From" address to authenticate users, so it is
|
|
|
|
// is not completely secure. To set this up, enter a complete email
|
|
|
|
// address like "bugs@phabricator.example.com" and then configure mail to
|
|
|
|
// that address so it routed to Phabricator (if you've already configured
|
|
|
|
// reply handlers, you're probably already done). See "Configuring Inbound
|
|
|
|
// Email" in the documentation for more information.
|
|
|
|
'metamta.maniphest.public-create-email' => null,
|
|
|
|
|
2011-08-21 21:03:57 +02:00
|
|
|
// If you enable 'metamta.public-replies', Phabricator uses "From" to
|
|
|
|
// authenticate users. You can additionally enable this setting to try to
|
|
|
|
// authenticate with 'Reply-To'. Note that this is completely spoofable and
|
|
|
|
// insecure (any user can set any 'Reply-To' address) but depending on the
|
|
|
|
// nature of your install or other deliverability conditions this might be
|
|
|
|
// okay. Generally, you can't do much more by spoofing Reply-To than be
|
|
|
|
// annoying (you can write but not read content). But, you know, this is
|
|
|
|
// still **COMPLETELY INSECURE**.
|
|
|
|
'metamta.insecure-auth-with-reply-to' => false,
|
|
|
|
|
2011-10-14 22:11:58 +02:00
|
|
|
// If you enable 'metamta.maniphest.public-create-email' and create an
|
|
|
|
// email address like "bugs@phabricator.example.com", it will default to
|
|
|
|
// rejecting mail which doesn't come from a known user. However, you might
|
|
|
|
// want to let anyone send email to this address; to do so, set a default
|
|
|
|
// author here (a Phabricator username). A typical use of this might be to
|
|
|
|
// create a "System Agent" user called "bugs" and use that name here. If you
|
|
|
|
// specify a valid username, mail will always be accepted and used to create
|
|
|
|
// a task, even if the sender is not a system user. The original email
|
|
|
|
// address will be stored in an 'From Email' field on the task.
|
|
|
|
'metamta.maniphest.default-public-author' => null,
|
|
|
|
|
2011-10-23 21:07:37 +02:00
|
|
|
// If this option is enabled, Phabricator will add a "Precedence: bulk"
|
|
|
|
// header to transactional mail (e.g., Differential, Maniphest and Herald
|
|
|
|
// notifications). This may improve the behavior of some auto-responder
|
|
|
|
// software and prevent it from replying. However, it may also cause
|
|
|
|
// deliverability issues -- notably, you currently can not send this header
|
|
|
|
// via Amazon SES, and enabling this option with SES will prevent delivery
|
|
|
|
// of any affected mail.
|
|
|
|
'metamta.precedence-bulk' => false,
|
|
|
|
|
Add optional "Re:" prefix to all threaded mail and allow disabling mail about
your own actions
Summary:
- Mail.app on Lion has cumbersome threading rules, see T782. Add an option to
stick "Re: " in front of all threaded mail so it behaves. This is horrible, but
apparently the least-horrible option.
- While I was in there, I added an option for T228.
Test Plan:
- Sent a bunch of threaded and unthreaded mail with varous "Re:" settings,
seemed to get "Re:" in the right places.
- Disabled email about my stuff, created a task with just me, got voided mail,
added a CC, got mail to just the CC.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, mkjones
Maniphest Tasks: T228, T782
Differential Revision: https://secure.phabricator.com/D1448
2012-01-18 05:32:28 +01:00
|
|
|
// Mail.app on OS X Lion won't respect threading headers unless the subject
|
|
|
|
// is prefixed with "Re:". If you enable this option, Phabricator will add
|
|
|
|
// "Re:" to the subject line of all mail which is expected to thread.
|
|
|
|
'metamta.re-prefix' => false,
|
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
|
2011-02-28 04:47:22 +01:00
|
|
|
// -- Auth ------------------------------------------------------------------ //
|
|
|
|
|
|
|
|
// Can users login with a username/password, or by following the link from
|
|
|
|
// a password reset email? You can disable this and configure one or more
|
|
|
|
// OAuth providers instead.
|
2011-02-28 19:15:42 +01:00
|
|
|
'auth.password-auth-enabled' => true,
|
|
|
|
|
Enable multiple web sessions
Summary:
Conduit already has multiple-session code, just move it to the main
establishSession() method and set a web session limit larger than 1.
NOTE: This will log everyone out since we no longer look for the "web" session,
only for "web-1", "web-2", ..., etc. Presumably this doesn't matter.
Test Plan:
Applied patch, was logged out. Logged in in Safari. Verified I was issued
"web-1". Logged in in Firefox. Verified I was issued "web-2".
Kept logging in and out until I got issued "web-5", then did it again and was
issued "web-1" with a new key.
Ran conduit methods and verified they work and correctly cycled session keys.
Reviewed By: tuomaspelkonen
Reviewers: tuomaspelkonen, jungejason, aran
Commenters: jungejason
CC: rm, fzamore, ola, aran, epriestley, jungejason, tuomaspelkonen
Differential Revision: 264
2011-05-11 13:52:32 +02:00
|
|
|
// Maximum number of simultaneous web sessions each user is permitted to have.
|
|
|
|
// Setting this to "1" will prevent a user from logging in on more than one
|
|
|
|
// browser at the same time.
|
|
|
|
'auth.sessions.web' => 5,
|
|
|
|
|
|
|
|
// Maximum number of simultaneous Conduit sessions each user is permitted
|
|
|
|
// to have.
|
Improve a race condition in session establishment code
Summary:
If you try to establish several sessions quickly (e.g., by running several
copies of "arc" at once, as in "arc x | arc y"), the current logic has a high
chance of making them all pick the same conduit session to refresh (since it's
the oldest one when each process selects the current sessions). This means they
all issue updates against "conduit-3" (or whatever) and one ends up with a bogus
session.
Instead, do an update against the table with the session key we read, so only
one process wins the race. If we don't win the race, try again until we do or
have tried every session slot.
Test Plan:
- Wiped conduit sessions, ran arc commands to verify the fresh session case.
- Ran a bunch of arc piped to itself, e.g. "arc list | arc list | arc list |
...". It succeeds up to the session limit, and above that gets failures as
expected.
- Manually checked the session table to make sure things seemed reasonable
there.
- Generally ran a bunch of arc commands.
- Logged out and logged in on the web interface.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran, btrahan
Maniphest Tasks: T687
Differential Revision: https://secure.phabricator.com/D1329
2012-01-06 02:55:21 +01:00
|
|
|
'auth.sessions.conduit' => 5,
|
Enable multiple web sessions
Summary:
Conduit already has multiple-session code, just move it to the main
establishSession() method and set a web session limit larger than 1.
NOTE: This will log everyone out since we no longer look for the "web" session,
only for "web-1", "web-2", ..., etc. Presumably this doesn't matter.
Test Plan:
Applied patch, was logged out. Logged in in Safari. Verified I was issued
"web-1". Logged in in Firefox. Verified I was issued "web-2".
Kept logging in and out until I got issued "web-5", then did it again and was
issued "web-1" with a new key.
Ran conduit methods and verified they work and correctly cycled session keys.
Reviewed By: tuomaspelkonen
Reviewers: tuomaspelkonen, jungejason, aran
Commenters: jungejason
CC: rm, fzamore, ola, aran, epriestley, jungejason, tuomaspelkonen
Differential Revision: 264
2011-05-11 13:52:32 +02:00
|
|
|
|
2011-07-24 20:02:08 +02:00
|
|
|
// Set this true to enable the Settings -> SSH Public Keys panel, which will
|
|
|
|
// allow users to associated SSH public keys with their accounts. This is only
|
|
|
|
// really useful if you're setting up services over SSH and want to use
|
|
|
|
// Phabricator for authentication; in most situations you can leave this
|
|
|
|
// disabled.
|
|
|
|
'auth.sshkeys.enabled' => false,
|
|
|
|
|
2011-02-28 19:15:42 +01:00
|
|
|
|
|
|
|
// -- Accounts -------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Is basic account information (email, real name, profile picture) editable?
|
|
|
|
// If you set up Phabricator to automatically synchronize account information
|
|
|
|
// from some other authoritative system, you can disable this to ensure
|
|
|
|
// information remains consistent across both systems.
|
|
|
|
'account.editable' => true,
|
|
|
|
|
Allow configuration of a minimum password length, unify password reset
interfaces
Summary:
- We have a hard-coded minimum length of 3 right now (and 1 in the other
interface), which is sort of silly.
- Provide a more reasonable default, and allow it to be configured.
- We have two password reset interfaces, one of which no longer actually
requires you to verify you own the account. This is more than a bit derp.
- Merge the interfaces into one, using either an email token or the account's
current password to let you change the password.
Test Plan:
- Reset password on an account.
- Changed password on an account.
- Created a new account, logged in, set the password.
- Tried to set a too-short password, got an error.
Reviewers: btrahan, jungejason, nh
Reviewed By: jungejason
CC: aran, jungejason
Maniphest Tasks: T766
Differential Revision: https://secure.phabricator.com/D1374
2012-01-12 05:26:38 +01:00
|
|
|
// When users set or reset a password, it must have at least this many
|
|
|
|
// characters.
|
|
|
|
'account.minimum-password-length' => 8,
|
|
|
|
|
2011-02-28 04:47:22 +01:00
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// -- Facebook ------------------------------------------------------------ //
|
2011-01-31 20:55:26 +01:00
|
|
|
|
|
|
|
// Can users use Facebook credentials to login to Phabricator?
|
|
|
|
'facebook.auth-enabled' => false,
|
|
|
|
|
2011-02-28 04:47:22 +01:00
|
|
|
// Can users use Facebook credentials to create new Phabricator accounts?
|
|
|
|
'facebook.registration-enabled' => true,
|
|
|
|
|
|
|
|
// Are Facebook accounts permanently linked to Phabricator accounts, or can
|
|
|
|
// the user unlink them?
|
|
|
|
'facebook.auth-permanent' => false,
|
|
|
|
|
2011-01-31 20:55:26 +01:00
|
|
|
// The Facebook "Application ID" to use for Facebook API access.
|
|
|
|
'facebook.application-id' => null,
|
|
|
|
|
|
|
|
// The Facebook "Application Secret" to use for Facebook API access.
|
|
|
|
'facebook.application-secret' => null,
|
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// -- GitHub ---------------------------------------------------------------- //
|
2011-02-21 07:47:56 +01:00
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// Can users use GitHub credentials to login to Phabricator?
|
2011-02-21 07:47:56 +01:00
|
|
|
'github.auth-enabled' => false,
|
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// Can users use GitHub credentials to create new Phabricator accounts?
|
2011-02-28 04:47:22 +01:00
|
|
|
'github.registration-enabled' => true,
|
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// Are GitHub accounts permanently linked to Phabricator accounts, or can
|
2011-02-28 04:47:22 +01:00
|
|
|
// the user unlink them?
|
|
|
|
'github.auth-permanent' => false,
|
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// The GitHub "Client ID" to use for GitHub API access.
|
2011-02-21 07:47:56 +01:00
|
|
|
'github.application-id' => null,
|
|
|
|
|
2012-02-03 02:25:31 +01:00
|
|
|
// The GitHub "Secret" to use for GitHub API access.
|
2011-02-21 07:47:56 +01:00
|
|
|
'github.application-secret' => null,
|
|
|
|
|
|
|
|
|
Add Google as an OAuth2 provider (BETA)
Summary:
This is pretty straightforward, except:
- We need to request read/write access to the address book to get the account
ID (which we MUST have) and real name, email and account name (which we'd like
to have). This is way more access than we should need, but there's apparently no
"get_loggedin_user_basic_information" type of call in the Google API suite (or,
at least, I couldn't find one).
- We can't get the profile picture or profile URI since there's no Plus API
access and Google users don't have meaningful public pages otherwise.
- Google doesn't save the fact that you've authorized the app, so every time
you want to login you need to reaffirm that you want to give us silly amounts of
access. Phabricator sessions are pretty long-duration though so this shouldn't
be a major issue.
Test Plan:
- Registered, logged out, and logged in with Google.
- Registered, logged out, and logged in with Facebook / Github to make sure I
didn't break anything.
- Linked / unlinked Google accounts.
Reviewers: Makinde, jungejason, nh, tuomaspelkonen, aran
Reviewed By: aran
CC: aran, epriestley, Makinde
Differential Revision: 916
2011-09-09 01:37:22 +02:00
|
|
|
// -- Google ---------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Can users use Google credentials to login to Phabricator?
|
|
|
|
'google.auth-enabled' => false,
|
|
|
|
|
|
|
|
// Can users use Google credentials to create new Phabricator accounts?
|
|
|
|
'google.registration-enabled' => true,
|
|
|
|
|
|
|
|
// Are Google accounts permanently linked to Phabricator accounts, or can
|
|
|
|
// the user unlink them?
|
|
|
|
'google.auth-permanent' => false,
|
|
|
|
|
|
|
|
// The Google "Client ID" to use for Google API access.
|
|
|
|
'google.application-id' => null,
|
|
|
|
|
|
|
|
// The Google "Client Secret" to use for Google API access.
|
|
|
|
'google.application-secret' => null,
|
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// -- Recaptcha ------------------------------------------------------------- //
|
|
|
|
|
2012-01-12 21:56:11 +01:00
|
|
|
// Is Recaptcha enabled? If disabled, captchas will not appear. You should
|
|
|
|
// enable Recaptcha if your install is public-facing, as it hinders
|
|
|
|
// brute-force attacks.
|
2011-02-01 01:50:08 +01:00
|
|
|
'recaptcha.enabled' => false,
|
2011-02-02 00:52:04 +01:00
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// Your Recaptcha public key, obtained from Recaptcha.
|
2011-01-31 20:55:26 +01:00
|
|
|
'recaptcha.public-key' => null,
|
2011-02-02 00:52:04 +01:00
|
|
|
|
2011-02-01 01:50:08 +01:00
|
|
|
// Your Recaptcha private key, obtained from Recaptcha.
|
2011-01-31 20:55:26 +01:00
|
|
|
'recaptcha.private-key' => null,
|
|
|
|
|
|
|
|
|
2011-02-11 23:58:45 +01:00
|
|
|
// -- Misc ------------------------------------------------------------------ //
|
|
|
|
|
|
|
|
// This is hashed with other inputs to generate CSRF tokens. If you want, you
|
|
|
|
// can change it to some other string which is unique to your install. This
|
|
|
|
// will make your install more secure in a vague, mostly theoretical way. But
|
|
|
|
// it will take you like 3 seconds of mashing on your keyboard to set it up so
|
|
|
|
// you might as well.
|
|
|
|
'phabricator.csrf-key' => '0b7ec0592e0a2829d8b71df2fa269b2c6172eca3',
|
|
|
|
|
2011-05-05 08:09:42 +02:00
|
|
|
// This is hashed with other inputs to generate mail tokens. If you want, you
|
|
|
|
// can change it to some other string which is unique to your install. In
|
|
|
|
// particular, you will want to do this if you accidentally send a bunch of
|
|
|
|
// mail somewhere you shouldn't have, to invalidate all old reply-to
|
|
|
|
// addresses.
|
|
|
|
'phabricator.mail-key' => '5ce3e7e8787f6e40dfae861da315a5cdf1018f12',
|
|
|
|
|
2011-02-11 23:58:45 +01:00
|
|
|
// Version string displayed in the footer. You probably should leave this
|
|
|
|
// alone.
|
|
|
|
'phabricator.version' => 'UNSTABLE',
|
2011-02-22 18:22:57 +01:00
|
|
|
|
2011-04-03 02:21:16 +02:00
|
|
|
// PHP requires that you set a timezone in your php.ini before using date
|
|
|
|
// functions, or it will emit a warning. If this isn't possible (for instance,
|
|
|
|
// because you are using HPHP) you can set some valid constant for
|
|
|
|
// date_default_timezone_set() here and Phabricator will set it on your
|
|
|
|
// behalf, silencing the warning.
|
|
|
|
'phabricator.timezone' => null,
|
|
|
|
|
2011-08-17 23:29:53 +02:00
|
|
|
// When unhandled exceptions occur, stack traces are hidden by default.
|
|
|
|
// You can enable traces for development to make it easier to debug problems.
|
|
|
|
'phabricator.show-stack-traces' => false,
|
|
|
|
|
2012-01-04 16:35:52 +01:00
|
|
|
// Shows an error callout if a page generated PHP errors, warnings or notices.
|
|
|
|
// This makes it harder to miss problems while developing Phabricator.
|
|
|
|
'phabricator.show-error-callout' => false,
|
|
|
|
|
2012-01-20 16:39:55 +01:00
|
|
|
// When users write comments which have URIs, they'll be automatically linked
|
2011-10-09 22:47:27 +02:00
|
|
|
// if the protocol appears in this set. This whitelist is primarily to prevent
|
|
|
|
// security issues like javascript:// URIs.
|
|
|
|
'uri.allowed-protocols' => array(
|
|
|
|
'http' => true,
|
|
|
|
'https' => true,
|
|
|
|
),
|
|
|
|
|
Add an option to switch tokenizers to use "ondemand" instead of "preloaded"
datasources
Summary:
The open source Phabricator has like 3,500 user accounts now and it takes a
while to pull/render them. Add an option to switch to ondemand for large
installs.
I'll follow up with a patch at some point to address a couple of name things:
- Denormalize last names into a keyed column (although this evidences some
bias toward the western world).
- Force all usernames to lowercase (sorry Girish, Makinde).
Also this patch is so clean it's crazy.
Didn't bother with other object types for now, I'm planning to dedicate a few
days to Projects at some point and I'll flesh out some auxiliary features like
this when I do that.
Test Plan: Switched to ondemand, verified data was queried dynamically. Switched
back, verified data was preloaded.
Reviewers: jungejason, nh, tuomaspelkonen, aran
Reviewed By: nh
CC: aran, epriestley, nh
Differential Revision: 923
2011-09-13 20:00:17 +02:00
|
|
|
// Tokenizers are UI controls which let the user select other users, email
|
|
|
|
// addresses, project names, etc., by typing the first few letters and having
|
|
|
|
// the control autocomplete from a list. They can load their data in two ways:
|
|
|
|
// either in a big chunk up front, or as the user types. By default, the data
|
|
|
|
// is loaded in a big chunk. This is simpler and performs better for small
|
|
|
|
// datasets. However, if you have a very large number of users or projects,
|
|
|
|
// (in the ballpark of more than a thousand), loading all that data may become
|
|
|
|
// slow enough that it's worthwhile to query on demand instead. This makes
|
|
|
|
// the typeahead slightly less responsive but overall performance will be much
|
|
|
|
// better if you have a ton of stuff. You can figure out which setting is
|
|
|
|
// best for your install by changing this setting and then playing with a
|
|
|
|
// user tokenizer (like the user selectors in Maniphest or Differential) and
|
|
|
|
// seeing which setting loads faster and feels better.
|
|
|
|
'tokenizer.ondemand' => false,
|
2011-08-08 00:14:23 +02:00
|
|
|
|
Provide a configuration flag to disable silliness in the UI
Summary: See comments. A few installs have remarked that their organizations
would prefer buttons labled "Submit" to buttons labeled "Clowncopterize".
Test Plan:
- In "serious" mode, verified Differential and Maniphest have serious strings,
tasks can not be closed out of spite, and reset/welcome emails are extremely
serious.
- In unserious mode, verified Differential and Maniphest have normal strings,
tasks can be closed out of spite, and reset/welcome emails are silly.
- This does not disable the "fax these changes" message in Arcanist (no
reasonable way for it to read the config value) or the rainbow syntax
highlighter (already removable though configuration).
Reviewers: moskov, jungejason, nh, tuomaspelkonen, aran
Reviewed By: moskov
CC: aran, moskov
Differential Revision: 1081
2011-11-04 23:16:34 +01:00
|
|
|
// By default, Phabricator includes some silly nonsense in the UI, such as
|
|
|
|
// a submit button called "Clowncopterize" in Differential and a call to
|
|
|
|
// "Leap Into Action". If you'd prefer more traditional UI strings like
|
|
|
|
// "Submit", you can set this flag to disable most of the jokes and easter
|
|
|
|
// eggs.
|
|
|
|
'phabricator.serious-business' => false,
|
|
|
|
|
|
|
|
|
2011-02-22 18:19:14 +01:00
|
|
|
// -- Files ----------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Lists which uploaded file types may be viewed in the browser. If a file
|
|
|
|
// has a mime type which does not appear in this list, it will always be
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
// downloaded instead of displayed. This is mainly a usability
|
2011-02-22 18:19:14 +01:00
|
|
|
// consideration, since browsers tend to freak out when viewing enormous
|
|
|
|
// binary files.
|
|
|
|
//
|
|
|
|
// The keys in this array are viewable mime types; the values are the mime
|
|
|
|
// types they will be delivered as when they are viewed in the browser.
|
Provide a setting which forces all file views to be served from an alternate
domain
Summary:
See D758, D759.
- Provide a strongly recommended setting which permits configuration of an
alternate domain.
- Lock cookies down better: set them on the exact domain, and use SSL-only if
the configuration is HTTPS.
- Prevent Phabriator from setting cookies on other domains.
This assumes D759 will land, it is not effective without that change.
Test Plan:
- Attempted to login from a different domain and was rejected.
- Logged out, logged back in normally.
- Put install in setup mode and verified it revealed a warning.
- Configured an alterate domain.
- Tried to view an image with an old URI, got a 400.
- Went to /files/ and verified links rendered to the alternate domain.
- Viewed an alternate domain file.
- Tried to view an alternate domain file without the secret key, got a 404.
Reviewers: andrewjcg, erling, aran, tuomaspelkonen, jungejason, codeblock
CC: aran
Differential Revision: 760
2011-08-02 07:24:00 +02:00
|
|
|
//
|
Move ALL files to serve from the alternate file domain, not just files without
"Content-Disposition: attachment"
Summary:
We currently serve some files off the primary domain (with "Content-Disposition:
attachment" + a CSRF check) and some files off the alternate domain (without
either).
This is not sufficient, because some UAs (like the iPad) ignore
"Content-Disposition: attachment". So there's an attack that goes like this:
- Alice uploads xss.html
- Alice says to Bob "hey download this file on your iPad"
- Bob clicks "Download" on Phabricator on his iPad, gets XSS'd.
NOTE: This removes the CSRF check for downloading files. The check is nice to
have but only raises the barrier to entry slightly. Between iPad / sniffing /
flash bytecode attacks, single-domain installs are simply insecure. We could
restore the check at some point in conjunction with a derived authentication
cookie (i.e., a mini-session-token which is only useful for downloading files),
but that's a lot of complexity to drop all at once.
(Because files are now authenticated only by knowing the PHID and secret key,
this also fixes the "no profile pictures in public feed while logged out"
issue.)
Test Plan: Viewed, info'd, and downloaded files
Reviewers: btrahan, arice, alok
Reviewed By: arice
CC: aran, epriestley
Maniphest Tasks: T843
Differential Revision: https://secure.phabricator.com/D1608
2012-02-14 23:52:27 +01:00
|
|
|
// IMPORTANT: Configure 'security.alternate-file-domain' above! Your install
|
|
|
|
// is NOT safe if it is left unconfigured.
|
2011-02-24 23:52:57 +01:00
|
|
|
'files.viewable-mime-types' => array(
|
2011-02-22 18:19:14 +01:00
|
|
|
'image/jpeg' => 'image/jpeg',
|
|
|
|
'image/jpg' => 'image/jpg',
|
|
|
|
'image/png' => 'image/png',
|
2011-03-25 05:32:26 +01:00
|
|
|
'image/gif' => 'image/gif',
|
2011-02-22 18:19:14 +01:00
|
|
|
'text/plain' => 'text/plain; charset=utf-8',
|
|
|
|
),
|
2011-01-31 20:55:26 +01:00
|
|
|
|
2011-05-02 23:20:24 +02:00
|
|
|
// Phabricator can proxy images from other servers so you can paste the URI
|
|
|
|
// to a funny picture of a cat into the comment box and have it show up as an
|
|
|
|
// image. However, this means the webserver Phabricator is running on will
|
|
|
|
// make HTTP requests to arbitrary URIs. If the server has access to internal
|
|
|
|
// resources, this could be a security risk. You should only enable it if you
|
|
|
|
// are installed entirely a VPN and VPN access is required to access
|
|
|
|
// Phabricator, or if the webserver has no special access to anything. If
|
|
|
|
// unsure, it is safer to leave this disabled.
|
|
|
|
'files.enable-proxy' => false,
|
|
|
|
|
2011-07-20 07:48:38 +02:00
|
|
|
|
|
|
|
// -- Storage --------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Phabricator allows users to upload files, and can keep them in various
|
|
|
|
// storage engines. This section allows you to configure which engines
|
|
|
|
// Phabricator will use, and how it will use them.
|
|
|
|
|
|
|
|
// The largest filesize Phabricator will store in the MySQL BLOB storage
|
|
|
|
// engine, which just uses a database table to store files. While this isn't a
|
|
|
|
// best practice, it's really easy to set up. This is hard-limited by the
|
|
|
|
// value of 'max_allowed_packet' in MySQL (since this often defaults to 1MB,
|
|
|
|
// the default here is slightly smaller than 1MB). Set this to 0 to disable
|
|
|
|
// use of the MySQL blob engine.
|
|
|
|
'storage.mysql-engine.max-size' => 1000000,
|
|
|
|
|
|
|
|
// Phabricator provides a local disk storage engine, which just writes files
|
|
|
|
// to some directory on local disk. The webserver must have read/write
|
|
|
|
// permissions on this directory. This is straightforward and suitable for
|
|
|
|
// most installs, but will not scale past one web frontend unless the path
|
|
|
|
// is actually an NFS mount, since you'll end up with some of the files
|
|
|
|
// written to each web frontend and no way for them to share. To use the
|
|
|
|
// local disk storage engine, specify the path to a directory here. To
|
|
|
|
// disable it, specify null.
|
|
|
|
'storage.local-disk.path' => null,
|
|
|
|
|
2011-07-31 22:54:58 +02:00
|
|
|
// If you want to store files in Amazon S3, specify an AWS access and secret
|
|
|
|
// key here and a bucket name below.
|
|
|
|
'amazon-s3.access-key' => null,
|
|
|
|
'amazon-s3.secret-key' => null,
|
|
|
|
|
|
|
|
// Set this to a valid Amazon S3 bucket to store files there. You must also
|
|
|
|
// configure S3 access keys above.
|
|
|
|
'storage.s3.bucket' => null,
|
2011-07-20 07:48:38 +02:00
|
|
|
|
|
|
|
// Phabricator uses a storage engine selector to choose which storage engine
|
|
|
|
// to use when writing file data. If you add new storage engines or want to
|
|
|
|
// provide very custom rules (e.g., write images to one storage engine and
|
|
|
|
// other files to a different one), you can provide an alternate
|
|
|
|
// implementation here. The default engine will use choose MySQL, Local Disk,
|
|
|
|
// and S3, in that order, if they have valid configurations above and a file
|
|
|
|
// fits within configured limits.
|
|
|
|
'storage.engine-selector' => 'PhabricatorDefaultFileStorageEngineSelector',
|
|
|
|
|
2011-08-08 00:14:23 +02:00
|
|
|
|
|
|
|
// -- Search ---------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Phabricator uses a search engine selector to choose which search engine
|
|
|
|
// to use when indexing and reconstructing documents, and when executing
|
|
|
|
// queries. You can override the engine selector to provide a new selector
|
|
|
|
// class which can select some custom engine you implement, if you want to
|
|
|
|
// store your documents in some search engine which does not have default
|
|
|
|
// support.
|
|
|
|
'search.engine-selector' => 'PhabricatorDefaultSearchEngineSelector',
|
|
|
|
|
|
|
|
|
2011-04-13 21:12:02 +02:00
|
|
|
// -- Differential ---------------------------------------------------------- //
|
|
|
|
|
|
|
|
'differential.revision-custom-detail-renderer' => null,
|
|
|
|
|
2011-05-26 22:13:36 +02:00
|
|
|
// Array for custom remarkup rules. The array should have a list of
|
|
|
|
// class names of classes that extend PhutilRemarkupRule
|
|
|
|
'differential.custom-remarkup-rules' => null,
|
|
|
|
|
|
|
|
// Array for custom remarkup block rules. The array should have a list of
|
|
|
|
// class names of classes that extend PhutilRemarkupEngineBlockRule
|
|
|
|
'differential.custom-remarkup-block-rules' => null,
|
2011-04-13 21:12:02 +02:00
|
|
|
|
2011-06-08 21:39:03 +02:00
|
|
|
// Set display word-wrap widths for Differential. Specify a dictionary of
|
|
|
|
// regular expressions mapping to column widths. The filename will be matched
|
|
|
|
// against each regexp in order until one matches. The default configuration
|
|
|
|
// uses a width of 100 for Java and 80 for other languages. Note that 80 is
|
|
|
|
// the greatest column width of all time. Changes here will not be immediately
|
2011-12-15 00:23:31 +01:00
|
|
|
// reflected in old revisions unless you purge the changeset render cache
|
|
|
|
// (with `./scripts/util/purge_cache.php --changesets`).
|
2011-06-08 21:39:03 +02:00
|
|
|
'differential.wordwrap' => array(
|
|
|
|
'/\.java$/' => 100,
|
|
|
|
'/.*/' => 80,
|
|
|
|
),
|
|
|
|
|
2011-07-22 22:15:11 +02:00
|
|
|
// List of file regexps were whitespace is meaningful and should not
|
|
|
|
// use 'ignore-all' by default
|
|
|
|
'differential.whitespace-matters' => array(
|
|
|
|
'/\.py$/',
|
2012-01-24 23:47:04 +01:00
|
|
|
'/\.l?hs$/',
|
2011-07-22 22:15:11 +02:00
|
|
|
),
|
|
|
|
|
2011-08-10 20:29:08 +02:00
|
|
|
'differential.field-selector' => 'DifferentialDefaultFieldSelector',
|
|
|
|
|
2012-02-12 10:36:05 +01:00
|
|
|
// Differential can show "Host" and "Path" fields on revisions, with
|
|
|
|
// information about the machine and working directory where the
|
2012-02-07 01:34:25 +01:00
|
|
|
// change came from. These fields are disabled by default because they may
|
2012-02-06 21:14:07 +01:00
|
|
|
// occasionally have sensitive information; you can set this to true to
|
|
|
|
// enable them.
|
|
|
|
'differential.show-host-field' => false,
|
|
|
|
|
2011-09-14 17:11:05 +02:00
|
|
|
// If you set this to true, users can "!accept" revisions via email (normally,
|
|
|
|
// they can take other actions but can not "!accept"). This action is disabled
|
|
|
|
// by default because email authentication can be configured to be very weak,
|
|
|
|
// and, socially, email "!accept" is kind of sketchy and implies revisions may
|
|
|
|
// not actually be receiving thorough review.
|
|
|
|
'differential.enable-email-accept' => false,
|
|
|
|
|
2011-10-24 21:27:16 +02:00
|
|
|
// If you set this to true, users won't need to login to view differential
|
|
|
|
// revisions. Anonymous users will have read-only access and won't be able to
|
|
|
|
// interact with the revisions.
|
|
|
|
'differential.anonymous-access' => false,
|
|
|
|
|
2012-01-19 18:39:54 +01:00
|
|
|
// List of file regexps that should be treated as if they are generated by
|
|
|
|
// an automatic process, and thus get hidden by default in differential
|
|
|
|
'differential.generated-paths' => array(
|
|
|
|
// '/config\.h$/',
|
|
|
|
// '#/autobuilt/#',
|
|
|
|
),
|
|
|
|
|
2011-08-10 20:29:08 +02:00
|
|
|
|
2011-04-13 21:12:02 +02:00
|
|
|
// -- Maniphest ------------------------------------------------------------- //
|
|
|
|
|
|
|
|
'maniphest.enabled' => true,
|
|
|
|
|
2011-08-05 18:44:43 +02:00
|
|
|
// Array of custom fields for Maniphest tasks. For details on adding custom
|
|
|
|
// fields to Maniphest, see "Maniphest User Guide: Adding Custom Fields".
|
2011-07-27 18:49:50 +02:00
|
|
|
'maniphest.custom-fields' => array(),
|
|
|
|
|
2011-08-05 18:44:43 +02:00
|
|
|
// Class which drives custom field construction. See "Maniphest User Guide:
|
|
|
|
// Adding Custom Fields" in the documentation for more information.
|
|
|
|
'maniphest.custom-task-extensions-class' => 'ManiphestDefaultTaskExtensions',
|
2011-08-08 00:14:23 +02:00
|
|
|
|
2012-02-18 01:08:35 +01:00
|
|
|
// -- Phriction ------------------------------------------------------------- //
|
|
|
|
|
|
|
|
'phriction.enabled' => true,
|
|
|
|
|
2011-05-27 21:50:02 +02:00
|
|
|
// -- Remarkup -------------------------------------------------------------- //
|
|
|
|
|
2011-05-29 19:20:24 +02:00
|
|
|
// If you enable this, linked YouTube videos will be embeded inline. This has
|
|
|
|
// mild security implications (you'll leak referrers to YouTube) and is pretty
|
|
|
|
// silly (but sort of awesome).
|
2011-05-27 21:50:02 +02:00
|
|
|
'remarkup.enable-embedded-youtube' => false,
|
|
|
|
|
2011-07-03 18:47:31 +02:00
|
|
|
|
|
|
|
// -- Garbage Collection ---------------------------------------------------- //
|
|
|
|
|
|
|
|
// Phabricator generates various logs and caches in the database which can
|
|
|
|
// be garbage collected after a while to make the total data size more
|
|
|
|
// manageable. To run garbage collection, launch a
|
|
|
|
// PhabricatorGarbageCollector daemon.
|
|
|
|
|
|
|
|
// Since the GC daemon can issue large writes and table scans, you may want to
|
|
|
|
// run it only during off hours or make sure it is scheduled so it doesn't
|
|
|
|
// overlap with backups. This determines when the daemon can start running
|
|
|
|
// each day.
|
|
|
|
'gcdaemon.run-at' => '12 AM',
|
|
|
|
|
|
|
|
// How many seconds after 'gcdaemon.run-at' the daemon may collect garbage
|
|
|
|
// for. By default it runs continuously, but you can set it to run for a
|
|
|
|
// limited period of time. For instance, if you do backups at 3 AM, you might
|
|
|
|
// run garbage collection for an hour beforehand. This is not a high-precision
|
|
|
|
// limit so you may want to leave some room for the GC to actually stop, and
|
|
|
|
// if you set it to something like 3 seconds you're on your own.
|
|
|
|
'gcdaemon.run-for' => 24 * 60 * 60,
|
|
|
|
|
|
|
|
// These 'ttl' keys configure how much old data the GC daemon keeps around.
|
|
|
|
// Objects older than the ttl will be collected. Set any value to 0 to store
|
|
|
|
// data indefinitely.
|
|
|
|
|
|
|
|
'gcdaemon.ttl.herald-transcripts' => 30 * (24 * 60 * 60),
|
|
|
|
'gcdaemon.ttl.daemon-logs' => 7 * (24 * 60 * 60),
|
2011-07-09 00:26:33 +02:00
|
|
|
'gcdaemon.ttl.differential-parse-cache' => 14 * (24 * 60 * 60),
|
2011-07-03 18:47:31 +02:00
|
|
|
|
|
|
|
|
2011-07-10 03:03:59 +02:00
|
|
|
// -- Feed ------------------------------------------------------------------ //
|
|
|
|
|
|
|
|
// If you set this to true, you can embed Phabricator activity feeds in other
|
|
|
|
// pages using iframes. These feeds are completely public, and a login is not
|
|
|
|
// required to view them! This is intended for things like open source
|
|
|
|
// projects that want to expose an activity feed on the project homepage.
|
|
|
|
'feed.public' => false,
|
|
|
|
|
Drydock Rough Cut
Summary:
Rough cut of Drydock. This is very basic and doesn't do much of use yet (it
//does// allocate EC2 machines as host resources and expose interfaces to them),
but I think the overall structure is more or less reasonable.
== Interfaces
Vision: Applications interact with Drydock resources through DrydockInterfaces,
like **command**, **filesystem** and **httpd** interfaces. Each interface allows
applications to perform some kind of operation on the resource, like executing
commands, reading/writing files, or configuring a web server. Interfaces have a
concrete, specific API:
// Filesystem Interface
$fs = $lease->getInterface('filesystem'); // Constants, some day?
$fs->writeFile('index.html', 'hello world!');
// Command Interface
$cmd = $lease->getInterface('command');
echo $cmd->execx('uptime');
// HTTPD Interface
$httpd = $lease->getInterface('httpd');
$httpd->restart();
Interfaces are mostly just stock, although installs might add new interfaces if
they expose different ways to interact with resources (for instance, a resource
might want to expose a new 'MongoDB' interface or whatever).
Currently: We have like part of a command interface.
== Leases
Vision: Leases keep track of which resources are in use, and what they're being
used for. They allow us to know when we need to allocate more resources (too
many sandcastles on the existing hosts, e.g.) and when we can release resources
(because they are no longer being used). They also give applications something
to hold while resources are being allocated.
// EXAMPLE: How this should work some day.
$allocator = new DrydockAllocator();
$allocator->setResourceType('sandcastle');
$allocator->setAttributes(
array(
'diffID' => $diff->getID(),
));
$lease = $allocator->allocate();
$diff->setSandcastleLeaseID($lease->getID());
// ...
if ($lease->getStatus() == DrydockLeaseStatus::STATUS_ACTIVE) {
$sandcastle_link = $lease->getInterface('httpd')->getURI('/');
} else {
$sandcastle_link = 'Still building your sandcastle...';
}
echo "Sandcastle for this diff: ".$sandcastle_link;
// EXAMPLE: How this actually works now.
$allocator = new DrydockAllocator();
$allocator->setResourceType('host');
// NOTE: Allocation is currently synchronous but will be task-driven soon.
$lease = $allocator->allocate();
Leases are completely stock, installs will not define new lease types.
Currently: Leases exist and work but are very very basic.
== Resources
Vision: Resources represent some actual thing we've put somewhere, whether it's
a host, a block of storage, a webroot, or whatever else. Applications interact
through resources by acquiring leases to them, and then getting interfaces
through these leases. The lease acquisition process has a side effect of
allocating new resources if a lease can't be acquired on existing resources
(e.g., the application wants storage but all storage resources are full) and
things are configured to autoscale.
Resources may themselves acquire leases in order to allocate. For instance, a
storage resource might first acquire a lease to a host resource. A 'test
scaffold' resource might lease a storage resource and a mysql resource.
Not all resources are auto-allocate: the entry-level version of Drydock is that
you manually allocate a couple boxes and configure them through the web console.
Then, e.g., 'storage' / 'webroot' resources allocate on top of them, but the
host pool itself does not autoscale.
Resources are completely stock, they are abstract shells representing any
arbitrary thing.
Currently: Resource exist ('host' only) but are very very basic.
== Blueprints
Vision: Blueprints contain instructions for building interfaces to, (possibly)
allocating, updating, managing, and destroying a specific type of resource in a
specific location. One way to think of them is that they are scripts for
creating and deleting resources. For example, the LocalHost, RemoteHost and
EC2Host blueprints can all manage 'host' resources.
Eventually, we will support more types of resources (storage, webroot,
sandcastle, test scaffold, phacility deployment) and more providers for resource
types, some of which will be in the Phabricator mainline and some of which will
be custom.
Blueprints are very custom and specific to application types, so installs will
define new blueprints if they are making significant use of Drydock.
Currently: They exist but have few capabilities. The stock blueprints do nearly
nothing useful. There is a technically functional blueprint for host allocation
in EC2.
== Allocator
This is just the actual code to execute the lease acquisition process.
Test Plan: Ran "drydock_control.php" script, it allocated a machine in EC2,
acquired a lease on it, interfaced with it, and then released the lease. Ran it
again, got a fresh lease on the existing resource.
Reviewers: btrahan, jungejason
Reviewed By: btrahan
CC: aran
Differential Revision: https://secure.phabricator.com/D1454
2012-01-11 20:18:40 +01:00
|
|
|
|
|
|
|
// -- Drydock --------------------------------------------------------------- //
|
|
|
|
|
|
|
|
// If you want to use Drydock's builtin EC2 Blueprints, configure your AWS
|
|
|
|
// EC2 credentials here.
|
|
|
|
'amazon-ec2.access-key' => null,
|
|
|
|
'amazon-ec2.secret-key' => null,
|
|
|
|
|
2011-02-24 23:52:57 +01:00
|
|
|
// -- Customization --------------------------------------------------------- //
|
|
|
|
|
|
|
|
// Paths to additional phutil libraries to load.
|
|
|
|
'load-libraries' => array(),
|
|
|
|
|
|
|
|
'aphront.default-application-configuration-class' =>
|
|
|
|
'AphrontDefaultApplicationConfiguration',
|
2011-02-28 04:47:22 +01:00
|
|
|
|
|
|
|
'controller.oauth-registration' =>
|
|
|
|
'PhabricatorOAuthDefaultRegistrationController',
|
2011-03-08 02:25:47 +01:00
|
|
|
|
2011-03-14 20:33:20 +01:00
|
|
|
|
|
|
|
// Directory that phd (the Phabricator daemon control script) should use to
|
|
|
|
// track running daemons.
|
|
|
|
'phd.pid-directory' => '/var/tmp/phd',
|
|
|
|
|
2011-05-09 10:10:40 +02:00
|
|
|
// This value is an input to the hash function when building resource hashes.
|
|
|
|
// It has no security value, but if you accidentally poison user caches (by
|
|
|
|
// pushing a bad patch or having something go wrong with a CDN, e.g.) you can
|
|
|
|
// change this to something else and rebuild the Celerity map to break user
|
|
|
|
// caches. Unless you are doing Celerity development, it is exceptionally
|
|
|
|
// unlikely that you need to modify this.
|
|
|
|
'celerity.resource-hash' => 'd9455ea150622ee044f7931dabfa52aa',
|
|
|
|
|
2011-05-11 12:42:02 +02:00
|
|
|
// In a development environment, it is desirable to force static resources
|
|
|
|
// (CSS and JS) to be read from disk on every request, so that edits to them
|
|
|
|
// appear when you reload the page even if you haven't updated the resource
|
|
|
|
// maps. This setting ensures requests will be verified against the state on
|
|
|
|
// disk. Generally, you should leave this off in production (caching behavior
|
|
|
|
// and performance improve with it off) but turn it on in development. (These
|
|
|
|
// settings are the defaults.)
|
|
|
|
'celerity.force-disk-reads' => false,
|
|
|
|
|
2011-08-31 22:25:13 +02:00
|
|
|
// You can respond to various application events by installing listeners,
|
|
|
|
// which will receive callbacks when interesting things occur. Specify a list
|
|
|
|
// of classes which extend PhabricatorEventListener here.
|
|
|
|
'events.listeners' => array(),
|
|
|
|
|
|
|
|
// -- Pygments -------------------------------------------------------------- //
|
|
|
|
|
2011-07-04 00:29:58 +02:00
|
|
|
// Phabricator can highlight PHP by default, but if you want syntax
|
|
|
|
// highlighting for other languages you should install the python package
|
|
|
|
// 'Pygments', make sure the 'pygmentize' script is available in the
|
|
|
|
// $PATH of the webserver, and then enable this.
|
|
|
|
'pygments.enabled' => false,
|
|
|
|
|
|
|
|
// In places that we display a dropdown to syntax-highlight code,
|
|
|
|
// this is where that list is defined.
|
|
|
|
// Syntax is 'lexer-name' => 'Display Name',
|
|
|
|
'pygments.dropdown-choices' => array(
|
|
|
|
'apacheconf' => 'Apache Configuration',
|
|
|
|
'bash' => 'Bash Scripting',
|
|
|
|
'brainfuck' => 'Brainf*ck',
|
|
|
|
'c' => 'C',
|
|
|
|
'cpp' => 'C++',
|
|
|
|
'css' => 'CSS',
|
|
|
|
'diff' => 'Diff',
|
|
|
|
'django' => 'Django Templating',
|
|
|
|
'erb' => 'Embedded Ruby/ERB',
|
|
|
|
'erlang' => 'Erlang',
|
|
|
|
'html' => 'HTML',
|
|
|
|
'infer' => 'Infer from title (extension)',
|
|
|
|
'java' => 'Java',
|
|
|
|
'js' => 'Javascript',
|
|
|
|
'mysql' => 'MySQL',
|
|
|
|
'perl' => 'Perl',
|
|
|
|
'php' => 'PHP',
|
|
|
|
'text' => 'Plain Text',
|
|
|
|
'python' => 'Python',
|
2011-08-02 19:32:59 +02:00
|
|
|
'rainbow' => 'Rainbow',
|
|
|
|
'remarkup' => 'Remarkup',
|
2011-07-04 00:29:58 +02:00
|
|
|
'ruby' => 'Ruby',
|
|
|
|
'xml' => 'XML',
|
|
|
|
),
|
|
|
|
|
|
|
|
'pygments.dropdown-default' => 'infer',
|
|
|
|
|
2011-07-06 21:12:17 +02:00
|
|
|
// This is an override list of regular expressions which allows you to choose
|
|
|
|
// what language files are highlighted as. If your projects have certain rules
|
|
|
|
// about filenames or use unusual or ambiguous language extensions, you can
|
|
|
|
// create a mapping here. This is an ordered dictionary of regular expressions
|
|
|
|
// which will be tested against the filename. They should map to either an
|
|
|
|
// explicit language as a string value, or a numeric index into the captured
|
|
|
|
// groups as an integer.
|
|
|
|
'syntax.filemap' => array(
|
|
|
|
// Example: Treat all '*.xyz' files as PHP.
|
|
|
|
// '@\\.xyz$@' => 'php',
|
|
|
|
|
|
|
|
// Example: Treat 'httpd.conf' as 'apacheconf'.
|
|
|
|
// '@/httpd\\.conf$@' => 'apacheconf',
|
|
|
|
|
|
|
|
// Example: Treat all '*.x.bak' file as '.x'. NOTE: we map to capturing
|
|
|
|
// group 1 by specifying the mapping as "1".
|
|
|
|
// '@\\.([^.]+)\\.bak$@' => 1,
|
2011-12-24 07:22:04 +01:00
|
|
|
|
|
|
|
'@\.arcconfig$@' => 'js',
|
2011-07-06 21:12:17 +02:00
|
|
|
),
|
|
|
|
|
2011-01-31 20:55:26 +01:00
|
|
|
);
|