diff --git a/conf/default.conf.php b/conf/default.conf.php
index 334e0a12b9..98b7d9ca7f 100644
--- a/conf/default.conf.php
+++ b/conf/default.conf.php
@@ -1,986 +1,982 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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,
 
   // 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,
 
   // Setting this to 'true' will invoke a special setup mode which helps guide
   // you through setting up Phabricator.
   'phabricator.setup'           => false,
 
-  // The default PHID for users who haven't uploaded a profile image. It should
-  // be 50x50px.
-  'user.default-profile-image-phid' => 'PHID-FILE-4d61229816cfe6f2b2a3',
-
 // -- IMPORTANT! Security! -------------------------------------------------- //
 
   // IMPORTANT: By default, Phabricator serves files from the same domain the
   // application lives on. This is convenient but not secure: it creates a large
   // class of vulnerabilities which can not be generally mitigated.
   //
   // 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
   // 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.
   //
   // It is STRONGLY RECOMMENDED that you configure this. Your install is NOT
   // SECURE unless you do so.
   'security.alternate-file-domain'  => null,
 
   // 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',
 
 
 // -- Customization --------------------------------------------------------- //
 
   // If you want to use a custom logo (e.g., for your company or organization),
   // copy 'webroot/rsrc/image/custom/example_template.png' to
   // 'webroot/rsrc/image/custom/custom.png' and set this to the URI you want it
   // to link to (like http://www.yourcompany.com/).
   'phabricator.custom.logo'   => null,
 
 
 // -- Access Policies ------------------------------------------------------- //
 
   // Phabricator allows you to set the visibility of objects (like repositories
   // and source code) to "Public", which means anyone on the internet can see
   // them, even without being logged in. This is great for open source, but
   // some installs may never want to make anything public, so this policy is
   // disabled by default. You can enable it here, which will let you set the
   // policy for objects to "Public". With this option disabled, the most open
   // policy is "All Users", which means users must be logged in to view things.
   'policy.allow-public'         => false,
 
 
 // -- Logging --------------------------------------------------------------- //
 
   // To enable the Phabricator access log, specify a path here. The Phabricator
   // access log can provide more detailed information about Phabricator access
   // than normal HTTP access logs (for instance, it can show logged-in users,
   // controllers, and other application data). If not set, no log will be
   // written.
   //
   // Make sure the PHP process can write to the log!
   'log.access.path'             => null,
 
   // Format for the access log. If not set, the default format will be used:
   //
   //  "[%D]\t%h\t%u\t%M\t%C\t%m\t%U\t%c\t%T"
   //
   // Available variables are:
   //
   //  - %c The HTTP response code.
   //  - %C The controller which handled the request.
   //  - %D The request date.
   //  - %e Epoch timestamp.
   //  - %h The webserver's host name.
   //  - %p The PID of the server process.
   //  - %R The HTTP referrer.
   //  - %r The remote IP.
   //  - %T The request duration, in microseconds.
   //  - %U The request path.
   //  - %u The logged-in user, if one is logged in.
   //  - %M The HTTP method.
   //  - %m For conduit, the Conduit method which was invoked.
   //
   // If a variable isn't available (for example, %m appears in the file format
   // but the request is not a Conduit request), it will be rendered as "-".
   //
   // Note that the default format is subject to change in the future, so if you
   // rely on the log's format, specify it explicitly.
   'log.access.format'           => null,
 
 
 // -- DarkConsole ----------------------------------------------------------- //
 
   // DarkConsole is a administrative debugging/profiling tool built into
   // Phabricator. You can leave it disabled unless you're developing against
   // Phabricator.
 
   // 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).
   'darkconsole.enabled'         => false,
 
   // 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
   // utilities to debug or profile logged-out pages. You must set
   // 'darkconsole.enabled' to use this option.
   'darkconsole.always-on'       => false,
 
 
   // 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',
     'github.application-secret',
     'phabricator.mail-key',
     'security.hmac-key',
   ),
 
 
 // --  MySQL  --------------------------------------------------------------- //
 
   // Class providing database configuration. It must implement
   // DatabaseConfigurationProvider.
   'mysql.configuration-provider' => 'DefaultDatabaseConfigurationProvider',
 
   // The username to use when connecting to MySQL.
   'mysql.user' => 'root',
 
   // The password to use when connecting to MySQL.
   'mysql.pass' => '',
 
   // 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).
   'mysql.host' => 'localhost',
 
   // The number of times to try reconnecting to the MySQL database
   'mysql.connection-retries' => 3,
 
   // Phabricator supports PHP extensions MySQL and MySQLi. It is possible to
   // implement also other access mechanism (e.g. PDO_MySQL). The class must
   // extend AphrontMySQLDatabaseConnectionBase.
   'mysql.implementation' => 'AphrontMySQLDatabaseConnection',
 
 
 // -- 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.
 
   // You can test your mail setup by going to "MetaMTA" in the web interface,
   // clicking "Send New Message", and then composing a message.
 
   // Default address to send mail "From".
   'metamta.default-address'     => 'noreply@example.com',
 
   // Domain used to generate Message-IDs.
   'metamta.domain'              => 'example.com',
 
   // When a message is sent to multiple recipients (for example, several
   // reviewers on a code review), Phabricator can either deliver one email to
   // everyone (e.g., "To: alincoln, usgrant, htaft") or separate emails to each
   // user (e.g., "To: alincoln", "To: usgrant", "To: htaft"). The major
   // advantages and disadvantages of each approach are:
   //
   //   - One mail to everyone:
   //     - Recipients can see To/Cc at a glance.
   //     - If you use mailing lists, you won't get duplicate mail if you're
   //       a normal recipient and also Cc'd on a mailing list.
   //     - Getting threading to work properly is harder, and probably requires
   //       making mail less useful by turning off options.
   //     - Sometimes people will "Reply All" and everyone will get two mails,
   //       one from the user and one from Phabricator turning their mail into
   //       a comment.
   //     - Not supported with a private reply-to address.
   //   - One mail to each user:
   //     - Recipients need to look in the mail body to see To/Cc.
   //     - If you use mailing lists, recipients may sometimes get duplicate
   //       mail.
   //     - Getting threading to work properly is easier, and threading settings
   //       can be customzied by each user.
   //     - "Reply All" no longer spams all other users.
   //     - Required if private reply-to addresses are configured.
   //
   // In the code, splitting one outbound email into one-per-recipient is
   // sometimes referred to as "multiplexing".
   'metamta.one-mail-per-recipient'  => true,
 
   // 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
   // PHPMailerLite, which will invoke "sendmail". This is appropriate
   // if sendmail actually works on your host, but if you haven't configured mail
   // 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,
 
   // 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,
 
   // 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',
 
   // 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,
 
   // 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]',
 
   // 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',
 
   // Prefix prepended to mail sent by Differential.
   'metamta.differential.subject-prefix' => '[Differential]',
 
   // 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,
 
   // To include patches in email bodies, set this to a positive integer. Patches
   // will be inlined if they are at most that many lines. For instance, a value
   // of 100 means "inline patches if they are no longer than 100 lines". By
   // default, patches are not inlined.
   'metamta.differential.inline-patches' => 0,
 
   // If you enable either of the options above, you can choose what format
   // patches are sent in. Valid options are 'unified' (like diff -u) or 'git'.
   'metamta.differential.patch-format'   => 'unified',
 
   // Prefix prepended to mail sent by Diffusion.
   'metamta.diffusion.subject-prefix' => '[Diffusion]',
 
   // See 'metamta.maniphest.reply-handler-domain'. This does the same thing,
   // but allows email replies via Diffusion.
   'metamta.diffusion.reply-handler-domain' => null,
 
   // See 'metamta.maniphest.reply-handler'. This does the same thing, but
   // affects Diffusion.
   'metamta.diffusion.reply-handler' => 'PhabricatorAuditReplyHandler',
 
   // 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,
 
   // 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,
 
   // 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,
 
   // 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,
 
   // 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,
 
   // 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. If
   // you've set 'metamta.one-mail-per-recipient', users can override this
   // setting in their preferences.
   'metamta.re-prefix' => false,
 
   // If true, allow MetaMTA to change mail subjects to put text like
   // '[Accepted]' and '[Commented]' in them. This makes subjects more useful,
   // but might break threading on some clients. If you've set
   // 'metamta.one-mail-per-recipient', users can override this setting in their
   // preferences.
   'metamta.vary-subjects' => true,
 
 
 // -- 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.
   'auth.password-auth-enabled'  => true,
 
   // 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.
   'auth.sessions.conduit'       => 5,
 
   // 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,
 
 
 // -- 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,
 
   // When users set or reset a password, it must have at least this many
   // characters.
   'account.minimum-password-length'  => 8,
 
 
 // -- Facebook OAuth -------------------------------------------------------- //
 
   // Can users use Facebook credentials to login to Phabricator?
   'facebook.auth-enabled'       => false,
 
   // 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,
 
   // 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,
 
 
 // -- GitHub OAuth ---------------------------------------------------------- //
 
   // Can users use GitHub credentials to login to Phabricator?
   'github.auth-enabled'         => false,
 
   // Can users use GitHub credentials to create new Phabricator accounts?
   'github.registration-enabled' => true,
 
   // Are GitHub accounts permanently linked to Phabricator accounts, or can
   // the user unlink them?
   'github.auth-permanent'       => false,
 
   // The GitHub "Client ID" to use for GitHub API access.
   'github.application-id'       => null,
 
   // The GitHub "Secret" to use for GitHub API access.
   'github.application-secret'   => null,
 
 
 // -- Google OAuth ---------------------------------------------------------- //
 
   // 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,
 
 // -- Phabricator OAuth ----------------------------------------------------- //
 
   // Meta-town -- Phabricator is itself an OAuth Provider
   // TODO -- T887 -- make this support multiple Phabricator instances!
 
   // The URI of the Phabricator instance to use as an OAuth server.
   'phabricator.oauth-uri'            => null,
 
   // Can users use Phabricator credentials to login to Phabricator?
   'phabricator.auth-enabled'         => false,
 
   // Can users use Phabricator credentials to create new Phabricator accounts?
   'phabricator.registration-enabled' => true,
 
   // Are Phabricator accounts permanently linked to Phabricator accounts, or can
   // the user unlink them?
   'phabricator.auth-permanent'       => false,
 
   // The Phabricator "Client ID" to use for Phabricator API access.
   'phabricator.application-id'       => null,
 
   // The Phabricator "Client Secret" to use for Phabricator API access.
   'phabricator.application-secret'   => null,
 
 // -- Disqus Comments ------------------------------------------------------- //
 
   // Should Phame users have Disqus comment widget, and if so what's the
   // website shortname to use? For example, secure.phabricator.org uses
   // "phabricator", which we registered with Disqus. If you aren't familiar
   // with Disqus, see:
   // Disqus quick start guide - http://docs.disqus.com/help/4/
   // Information on shortnames - http://docs.disqus.com/help/68/
   'disqus.shortname'            => null,
 
 // -- Recaptcha ------------------------------------------------------------- //
 
   // 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.
   'recaptcha.enabled'           => false,
 
   // Your Recaptcha public key, obtained from Recaptcha.
   'recaptcha.public-key'        => null,
 
   // Your Recaptcha private key, obtained from Recaptcha.
   'recaptcha.private-key'       => null,
 
 
 // -- 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',
 
   // 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',
 
   // Version string displayed in the footer. You probably should leave this
   // alone.
   'phabricator.version'         => 'UNSTABLE',
 
   // 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,
 
   // 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,
 
   // 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,
 
   // When users write comments which have URIs, they'll be automatically linked
   // 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,
   ),
 
   // 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,
 
   // 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,
 
 
 // -- 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
   // downloaded instead of displayed. This is mainly a usability
   // 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.
   //
   // IMPORTANT: Configure 'security.alternate-file-domain' above! Your install
   // is NOT safe if it is left unconfigured.
   'files.viewable-mime-types' => array(
     'image/jpeg'  => 'image/jpeg',
     'image/jpg'   => 'image/jpg',
     'image/png'   => 'image/png',
     'image/gif'   => 'image/gif',
     'text/plain'  => 'text/plain; charset=utf-8',
 
     // ".ico" favicon files, which have mime type diversity. See:
     // http://en.wikipedia.org/wiki/ICO_(file_format)#MIME_type
     'image/x-ico'               => 'image/x-icon',
     'image/x-icon'              => 'image/x-icon',
     'image/vnd.microsoft.icon'  => 'image/x-icon',
   ),
 
   // List of mime types which can be used as the source for an <img /> tag.
   // This should be a subset of 'files.viewable-mime-types' and exclude files
   // like text.
   'files.image-mime-types' => array(
     'image/jpeg'                => true,
     'image/jpg'                 => true,
     'image/png'                 => true,
     'image/gif'                 => true,
     'image/x-ico'               => true,
     'image/x-icon'              => true,
     'image/vnd.microsoft.icon'  => true,
   ),
 
   // 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,
 
 
 // -- 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,
 
   // 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,
 
   // 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',
 
 
 // -- Search ---------------------------------------------------------------- //
 
   // Phabricator supports Elastic Search; to use it, specify a host like
   // 'http://elastic.example.com:9200/' here.
   'search.elastic.host'     => null,
 
   // 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',
 
 
 // -- Differential ---------------------------------------------------------- //
 
   'differential.revision-custom-detail-renderer'  => null,
 
   // 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,
 
   // 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
   // reflected in old revisions unless you purge the changeset render cache
   // (with `./scripts/util/purge_cache.php --changesets`).
   'differential.wordwrap' => array(
     '/\.java$/' => 100,
     '/.*/'      => 80,
   ),
 
   // List of file regexps were whitespace is meaningful and should not
   // use 'ignore-all' by default
   'differential.whitespace-matters' => array(
     '/\.py$/',
     '/\.l?hs$/',
   ),
 
   'differential.field-selector' => 'DifferentialDefaultFieldSelector',
 
   // Differential can show "Host" and "Path" fields on revisions, with
   // information about the machine and working directory where the
   // change came from. These fields are disabled by default because they may
   // occasionally have sensitive information; you can set this to true to
   // enable them.
   'differential.show-host-field'  => false,
 
   // Differential has a required "Test Plan" field by default, which requires
   // authors to fill out information about how they verified the correctness of
   // their changes when sending code for review. If you'd prefer not to use
   // this field, you can disable it here. You can also make it optional
   // (instead of required) below.
   'differential.show-test-plan-field' => true,
 
   // Differential has a required "Test Plan" field by default. You can make it
   // optional by setting this to false. You can also completely remove it above,
   // if you prefer.
   'differential.require-test-plan-field' => true,
 
   // 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,
 
   // 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,
 
   // 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/#',
   ),
 
 
 // -- Maniphest ------------------------------------------------------------- //
 
   'maniphest.enabled' => true,
 
   // Array of custom fields for Maniphest tasks. For details on adding custom
   // fields to Maniphest, see "Maniphest User Guide: Adding Custom Fields".
   'maniphest.custom-fields' => array(),
 
   // 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',
 
 // -- Phriction ------------------------------------------------------------- //
 
   'phriction.enabled' => true,
 
 // -- Remarkup -------------------------------------------------------------- //
 
   // 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).
   'remarkup.enable-embedded-youtube' => false,
 
 
 // -- 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),
   'gcdaemon.ttl.differential-parse-cache'   => 14 * (24 * 60 * 60),
 
 
 // -- 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 --------------------------------------------------------------- //
 
   // 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,
 
 // -- Customization --------------------------------------------------------- //
 
   // Paths to additional phutil libraries to load.
   'load-libraries' => array(),
 
   'aphront.default-application-configuration-class' =>
     'AphrontDefaultApplicationConfiguration',
 
   'controller.oauth-registration' =>
     'PhabricatorOAuthDefaultRegistrationController',
 
 
   // Directory that phd (the Phabricator daemon control script) should use to
   // track running daemons.
   'phd.pid-directory' => '/var/tmp/phd',
 
   // 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',
 
   // 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,
 
   // Minify static resources by removing whitespace and comments. You should
   // enable this in production, but disable it in development.
   'celerity.minify' => false,
 
   // 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 -------------------------------------------------------------- //
 
   // 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',
     'rainbow' => 'Rainbow',
     'remarkup' => 'Remarkup',
     'ruby' => 'Ruby',
     'xml' => 'XML',
   ),
 
   'pygments.dropdown-default' => 'infer',
 
   // 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,
 
     '@\.arcconfig$@' => 'js',
   ),
 
 );
diff --git a/src/applications/conduit/method/user/base/ConduitAPI_user_Method.php b/src/applications/conduit/method/user/base/ConduitAPI_user_Method.php
index ec73278b95..c74029b021 100644
--- a/src/applications/conduit/method/user/base/ConduitAPI_user_Method.php
+++ b/src/applications/conduit/method/user/base/ConduitAPI_user_Method.php
@@ -1,43 +1,35 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 /**
  * @group conduit
  */
 abstract class ConduitAPI_user_Method extends ConduitAPIMethod {
 
   protected function buildUserInformationDictionary(PhabricatorUser $user) {
-    $src_phid = $user->getProfileImagePHID();
-    $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $src_phid);
-    if ($file) {
-      $picture = $file->getBestURI();
-    } else {
-      $picture = null;
-    }
-
     return array(
       'phid'      => $user->getPHID(),
       'userName'  => $user->getUserName(),
       'realName'  => $user->getRealName(),
       'email'     => $user->getEmail(),
-      'image'     => $picture,
+      'image'     => $user->loadProfileImageURI(),
       'uri'       => PhabricatorEnv::getURI('/p/'.$user->getUsername().'/'),
     );
   }
 
 }
diff --git a/src/applications/conduit/method/user/base/__init__.php b/src/applications/conduit/method/user/base/__init__.php
index 1780cf774f..a91e4dcbd1 100644
--- a/src/applications/conduit/method/user/base/__init__.php
+++ b/src/applications/conduit/method/user/base/__init__.php
@@ -1,16 +1,13 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'applications/conduit/method/base');
-phutil_require_module('phabricator', 'applications/files/storage/file');
 phutil_require_module('phabricator', 'infrastructure/env');
 
-phutil_require_module('phutil', 'utils');
-
 
 phutil_require_source('ConduitAPI_user_Method.php');
diff --git a/src/applications/people/controller/profile/PhabricatorPeopleProfileController.php b/src/applications/people/controller/profile/PhabricatorPeopleProfileController.php
index 111795f2df..ff91c71758 100644
--- a/src/applications/people/controller/profile/PhabricatorPeopleProfileController.php
+++ b/src/applications/people/controller/profile/PhabricatorPeopleProfileController.php
@@ -1,222 +1,216 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorPeopleProfileController
   extends PhabricatorPeopleController {
 
   private $username;
   private $page;
 
   public function willProcessRequest(array $data) {
     $this->username = idx($data, 'username');
     $this->page = idx($data, 'page');
   }
 
   public function processRequest() {
 
     $viewer = $this->getRequest()->getUser();
 
     $user = id(new PhabricatorUser())->loadOneWhere(
       'userName = %s',
       $this->username);
     if (!$user) {
       return new Aphront404Response();
     }
 
     require_celerity_resource('phabricator-profile-css');
 
     $profile = id(new PhabricatorUserProfile())->loadOneWhere(
       'userPHID = %s',
       $user->getPHID());
     if (!$profile) {
       $profile = new PhabricatorUserProfile();
     }
     $username = phutil_escape_uri($user->getUserName());
 
     $nav = new AphrontSideNavFilterView();
     $nav->setBaseURI(new PhutilURI('/p/'.$username.'/'));
     $nav->addFilter('feed', 'Feed');
     $nav->addFilter('about', 'About');
 
     $nav->addSpacer();
     $nav->addLabel('Activity');
 
     $external_arrow = "\xE2\x86\x97";
     $nav->addFilter(
       null,
       "Revisions {$external_arrow}",
       '/differential/filter/revisions/'.$username.'/');
 
     $nav->addFilter(
       null,
       "Tasks {$external_arrow}",
       '/maniphest/view/action/?users='.$user->getPHID());
 
     $nav->addFilter(
       null,
       "Commits {$external_arrow}",
       '/audit/view/author/'.$username.'/');
 
     $oauths = id(new PhabricatorUserOAuthInfo())->loadAllWhere(
       'userID = %d',
       $user->getID());
     $oauths = mpull($oauths, null, 'getOAuthProvider');
 
     $providers = PhabricatorOAuthProvider::getAllProviders();
     $added_spacer = false;
     foreach ($providers as $provider) {
       if (!$provider->isProviderEnabled()) {
         continue;
       }
 
       $provider_key = $provider->getProviderKey();
 
       if (!isset($oauths[$provider_key])) {
         continue;
       }
 
       $name = $provider->getProviderName().' Profile';
       $href = $oauths[$provider_key]->getAccountURI();
 
       if ($href) {
         if (!$added_spacer) {
           $nav->addSpacer();
           $nav->addLabel('Linked Accounts');
           $added_spacer = true;
         }
         $nav->addFilter(null, $name.' '.$external_arrow, $href);
       }
     }
 
     $this->page = $nav->selectFilter($this->page, 'feed');
 
     switch ($this->page) {
       case 'feed':
         $content = $this->renderUserFeed($user);
         break;
       case 'about':
         $content = $this->renderBasicInformation($user, $profile);
         break;
       default:
         throw new Exception("Unknown page '{$this->page}'!");
     }
 
-    $src_phid = $user->getProfileImagePHID();
-    $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $src_phid);
-    if ($file) {
-      $picture = $file->getBestURI();
-    } else {
-      $picture = null;
-    }
+    $picture = $user->loadProfileImageURI();
 
     $header = new PhabricatorProfileHeaderView();
     $header
       ->setProfilePicture($picture)
       ->setName($user->getUserName().' ('.$user->getRealName().')')
       ->setDescription($profile->getTitle());
 
     $header->appendChild($nav);
     $nav->appendChild(
       '<div style="padding: 1em;">'.$content.'</div>');
 
     if ($user->getPHID() == $viewer->getPHID()) {
       $nav->addSpacer();
       $nav->addFilter(null, 'Edit Profile...', '/settings/page/profile/');
     }
 
     if ($viewer->getIsAdmin()) {
       $nav->addSpacer();
       $nav->addFilter(
         null,
         'Administrate User...',
         '/people/edit/'.$user->getID().'/');
     }
 
     return $this->buildStandardPageResponse(
       $header,
       array(
         'title' => $user->getUsername(),
       ));
   }
 
   private function renderBasicInformation($user, $profile) {
 
     $blurb = nonempty(
       $profile->getBlurb(),
       '//Nothing is known about this rare specimen.//');
 
     $engine = PhabricatorMarkupEngine::newProfileMarkupEngine();
     $blurb = $engine->markupText($blurb);
 
     $viewer = $this->getRequest()->getUser();
 
     $content =
       '<div class="phabricator-profile-info-group">
         <h1 class="phabricator-profile-info-header">Basic Information</h1>
         <div class="phabricator-profile-info-pane">
           <table class="phabricator-profile-info-table">
             <tr>
               <th>PHID</th>
               <td>'.phutil_escape_html($user->getPHID()).'</td>
             </tr>
             <tr>
               <th>User Since</th>
               <td>'.phabricator_datetime($user->getDateCreated(),
                                          $viewer).
              '</td>
             </tr>
           </table>
         </div>
       </div>';
     $content .=
       '<div class="phabricator-profile-info-group">
         <h1 class="phabricator-profile-info-header">Flavor Text</h1>
         <div class="phabricator-profile-info-pane">
           <table class="phabricator-profile-info-table">
             <tr>
               <th>Blurb</th>
               <td>'.$blurb.'</td>
             </tr>
           </table>
         </div>
       </div>';
 
     return $content;
   }
 
   private function renderUserFeed(PhabricatorUser $user) {
     $query = new PhabricatorFeedQuery();
     $query->setFilterPHIDs(
       array(
         $user->getPHID(),
       ));
     $stories = $query->execute();
 
     $builder = new PhabricatorFeedBuilder($stories);
     $builder->setUser($this->getRequest()->getUser());
     $view = $builder->buildView();
 
     return
       '<div class="phabricator-profile-info-group">
         <h1 class="phabricator-profile-info-header">Activity Feed</h1>
         <div class="phabricator-profile-info-pane">
           '.$view->render().'
         </div>
       </div>';
   }
 }
diff --git a/src/applications/people/controller/profile/__init__.php b/src/applications/people/controller/profile/__init__.php
index 110a677ab4..a4f50fdc45 100644
--- a/src/applications/people/controller/profile/__init__.php
+++ b/src/applications/people/controller/profile/__init__.php
@@ -1,29 +1,28 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'aphront/response/404');
 phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
 phutil_require_module('phabricator', 'applications/feed/builder/feed');
 phutil_require_module('phabricator', 'applications/feed/query');
-phutil_require_module('phabricator', 'applications/files/storage/file');
 phutil_require_module('phabricator', 'applications/markup/engine');
 phutil_require_module('phabricator', 'applications/people/controller/base');
 phutil_require_module('phabricator', 'applications/people/storage/profile');
 phutil_require_module('phabricator', 'applications/people/storage/user');
 phutil_require_module('phabricator', 'applications/people/storage/useroauthinfo');
 phutil_require_module('phabricator', 'infrastructure/celerity/api');
 phutil_require_module('phabricator', 'view/layout/profileheader');
 phutil_require_module('phabricator', 'view/layout/sidenavfilter');
 phutil_require_module('phabricator', 'view/utils');
 
 phutil_require_module('phutil', 'markup');
 phutil_require_module('phutil', 'parser/uri');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorPeopleProfileController.php');
diff --git a/src/applications/people/controller/settings/panels/profile/PhabricatorUserProfileSettingsPanelController.php b/src/applications/people/controller/settings/panels/profile/PhabricatorUserProfileSettingsPanelController.php
index 8c8e75c859..4856a04d5a 100644
--- a/src/applications/people/controller/settings/panels/profile/PhabricatorUserProfileSettingsPanelController.php
+++ b/src/applications/people/controller/settings/panels/profile/PhabricatorUserProfileSettingsPanelController.php
@@ -1,195 +1,188 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorUserProfileSettingsPanelController
   extends PhabricatorUserSettingsPanelController {
 
   public function processRequest() {
 
     $request = $this->getRequest();
     $user = $request->getUser();
 
     $profile = id(new PhabricatorUserProfile())->loadOneWhere(
       'userPHID = %s',
       $user->getPHID());
     if (!$profile) {
       $profile = new PhabricatorUserProfile();
       $profile->setUserPHID($user->getPHID());
     }
 
     $supported_formats = PhabricatorFile::getTransformableImageFormats();
 
     $e_image = null;
     $errors = array();
     if ($request->isFormPost()) {
       $profile->setTitle($request->getStr('title'));
       $profile->setBlurb($request->getStr('blurb'));
 
       $sex = $request->getStr('sex');
       if (in_array($sex, array('m', 'f'))) {
         $user->setSex($sex);
       } else {
         $user->setSex(null);
       }
 
       if (!empty($_FILES['image'])) {
         $err = idx($_FILES['image'], 'error');
         if ($err != UPLOAD_ERR_NO_FILE) {
           $file = PhabricatorFile::newFromPHPUpload(
             $_FILES['image'],
             array(
               'authorPHID' => $user->getPHID(),
             ));
           $okay = $file->isTransformableImage();
           if ($okay) {
             $xformer = new PhabricatorImageTransformer();
 
             // Generate the large picture for the profile page.
             $large_xformed = $xformer->executeProfileTransform(
               $file,
               $width = 280,
               $min_height = 140,
               $max_height = 420);
             $profile->setProfileImagePHID($large_xformed->getPHID());
 
             // Generate the small picture for comments, etc.
             $small_xformed = $xformer->executeProfileTransform(
               $file,
               $width = 50,
               $min_height = 50,
               $max_height = 50);
             $user->setProfileImagePHID($small_xformed->getPHID());
           } else {
             $e_image = 'Not Supported';
             $errors[] =
               'This server only supports these image formats: '.
               implode(', ', $supported_formats).'.';
           }
         }
       }
 
       if (!$errors) {
         $user->save();
         $profile->save();
         $response = id(new AphrontRedirectResponse())
           ->setURI('/settings/page/profile/?saved=true');
         return $response;
       }
     }
 
     $error_view = null;
     if ($errors) {
       $error_view = new AphrontErrorView();
       $error_view->setTitle('Form Errors');
       $error_view->setErrors($errors);
     } else {
       if ($request->getStr('saved')) {
         $error_view = new AphrontErrorView();
         $error_view->setSeverity(AphrontErrorView::SEVERITY_NOTICE);
         $error_view->setTitle('Changes Saved');
         $error_view->appendChild('<p>Your changes have been saved.</p>');
         $error_view = $error_view->render();
       }
     }
 
-    $file = id(new PhabricatorFile())->loadOneWhere(
-      'phid = %s',
-      $user->getProfileImagePHID());
-    if ($file) {
-      $img_src = $file->getBestURI();
-    } else {
-      $img_src = null;
-    }
+    $img_src = $user->loadProfileImageURI();
     $profile_uri = PhabricatorEnv::getURI('/p/'.$user->getUsername().'/');
 
     $sexes = array(
       '' => 'Unknown',
       'm' => 'Male',
       'f' => 'Female',
     );
 
     $form = new AphrontFormView();
     $form
       ->setUser($request->getUser())
       ->setAction('/settings/page/profile/')
       ->setEncType('multipart/form-data')
       ->appendChild(
         id(new AphrontFormTextControl())
           ->setLabel('Title')
           ->setName('title')
           ->setValue($profile->getTitle())
           ->setCaption('Serious business title.'))
       ->appendChild(
         id(new AphrontFormSelectControl())
           ->setOptions($sexes)
           ->setLabel('Sex')
           ->setName('sex')
           ->setValue($user->getSex()))
       ->appendChild(
         id(new AphrontFormMarkupControl())
           ->setLabel('Profile URI')
           ->setValue(
             phutil_render_tag(
               'a',
               array(
                 'href' => $profile_uri,
               ),
               phutil_escape_html($profile_uri))))
       ->appendChild(
         '<p class="aphront-form-instructions">Write something about yourself! '.
         'Make sure to include <strong>important information</strong> like '.
         'your favorite pokemon and which Starcraft race you play.</p>')
       ->appendChild(
         id(new AphrontFormTextAreaControl())
           ->setLabel('Blurb')
           ->setName('blurb')
           ->setValue($profile->getBlurb()))
       ->appendChild(
         id(new AphrontFormMarkupControl())
           ->setLabel('Profile Image')
           ->setValue(
             phutil_render_tag(
               'img',
               array(
                 'src' => $img_src,
               ))))
       ->appendChild(
         id(new AphrontFormFileControl())
           ->setLabel('Change Image')
           ->setName('image')
           ->setError($e_image)
           ->setCaption('Supported formats: '.implode(', ', $supported_formats)))
       ->appendChild(
         id(new AphrontFormSubmitControl())
           ->setValue('Save')
           ->addCancelButton('/p/'.$user->getUsername().'/'));
 
     $panel = new AphrontPanelView();
     $panel->setHeader('Edit Profile Details');
     $panel->appendChild($form);
     $panel->setWidth(AphrontPanelView::WIDTH_FORM);
 
     return id(new AphrontNullView())
       ->appendChild(
         array(
           $error_view,
           $panel,
         ));
   }
 
 }
diff --git a/src/applications/people/storage/user/PhabricatorUser.php b/src/applications/people/storage/user/PhabricatorUser.php
index b5d495ac53..4612b0456a 100644
--- a/src/applications/people/storage/user/PhabricatorUser.php
+++ b/src/applications/people/storage/user/PhabricatorUser.php
@@ -1,526 +1,537 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorUser extends PhabricatorUserDAO {
 
   const SESSION_TABLE = 'phabricator_session';
   const NAMETOKEN_TABLE = 'user_nametoken';
 
   protected $phid;
   protected $userName;
   protected $realName;
   protected $email;
   protected $sex;
   protected $passwordSalt;
   protected $passwordHash;
   protected $profileImagePHID;
   protected $timezoneIdentifier = '';
 
   protected $consoleEnabled = 0;
   protected $consoleVisible = 0;
   protected $consoleTab = '';
 
   protected $conduitCertificate;
 
   protected $isSystemAgent = 0;
   protected $isAdmin = 0;
   protected $isDisabled = 0;
 
   private $preferences = null;
 
   protected function readField($field) {
     switch ($field) {
-      case 'profileImagePHID':
-        return nonempty(
-          $this->profileImagePHID,
-          PhabricatorEnv::getEnvConfig('user.default-profile-image-phid'));
       case 'timezoneIdentifier':
         // If the user hasn't set one, guess the server's time.
         return nonempty(
           $this->timezoneIdentifier,
           date_default_timezone_get());
       // Make sure these return booleans.
       case 'isAdmin':
         return (bool)$this->isAdmin;
       case 'isDisabled':
         return (bool)$this->isDisabled;
       case 'isSystemAgent':
         return (bool)$this->isSystemAgent;
       default:
         return parent::readField($field);
     }
   }
 
   public function getConfiguration() {
     return array(
       self::CONFIG_AUX_PHID => true,
       self::CONFIG_PARTIAL_OBJECTS => true,
     ) + parent::getConfiguration();
   }
 
   public function generatePHID() {
     return PhabricatorPHID::generateNewPHID(
       PhabricatorPHIDConstants::PHID_TYPE_USER);
   }
 
   public function setPassword($password) {
     if (!$this->getPHID()) {
       throw new Exception(
         "You can not set a password for an unsaved user because their PHID ".
         "is a salt component in the password hash.");
     }
 
     if (!strlen($password)) {
       $this->setPasswordHash('');
     } else {
       $this->setPasswordSalt(md5(mt_rand()));
       $hash = $this->hashPassword($password);
       $this->setPasswordHash($hash);
     }
     return $this;
   }
 
   public function isLoggedIn() {
     return !($this->getPHID() === null);
   }
 
   public function save() {
     if (!$this->getConduitCertificate()) {
       $this->setConduitCertificate($this->generateConduitCertificate());
     }
     $result = parent::save();
 
     $this->updateNameTokens();
     PhabricatorSearchUserIndexer::indexUser($this);
 
     return $result;
   }
 
   private function generateConduitCertificate() {
     return Filesystem::readRandomCharacters(255);
   }
 
   public function comparePassword($password) {
     if (!strlen($password)) {
       return false;
     }
     if (!strlen($this->getPasswordHash())) {
       return false;
     }
     $password = $this->hashPassword($password);
     return ($password === $this->getPasswordHash());
   }
 
   private function hashPassword($password) {
     $password = $this->getUsername().
                 $password.
                 $this->getPHID().
                 $this->getPasswordSalt();
     for ($ii = 0; $ii < 1000; $ii++) {
       $password = md5($password);
     }
     return $password;
   }
 
   const CSRF_CYCLE_FREQUENCY  = 3600;
   const CSRF_TOKEN_LENGTH     = 16;
 
   const EMAIL_CYCLE_FREQUENCY = 86400;
   const EMAIL_TOKEN_LENGTH    = 24;
 
   public function getCSRFToken($offset = 0) {
     return $this->generateToken(
       time() + (self::CSRF_CYCLE_FREQUENCY * $offset),
       self::CSRF_CYCLE_FREQUENCY,
       PhabricatorEnv::getEnvConfig('phabricator.csrf-key'),
       self::CSRF_TOKEN_LENGTH);
   }
 
   public function validateCSRFToken($token) {
 
     if (!$this->getPHID()) {
       return true;
     }
 
     // When the user posts a form, we check that it contains a valid CSRF token.
     // Tokens cycle each hour (every CSRF_CYLCE_FREQUENCY seconds) and we accept
     // either the current token, the next token (users can submit a "future"
     // token if you have two web frontends that have some clock skew) or any of
     // the last 6 tokens. This means that pages are valid for up to 7 hours.
     // There is also some Javascript which periodically refreshes the CSRF
     // tokens on each page, so theoretically pages should be valid indefinitely.
     // However, this code may fail to run (if the user loses their internet
     // connection, or there's a JS problem, or they don't have JS enabled).
     // Choosing the size of the window in which we accept old CSRF tokens is
     // an issue of balancing concerns between security and usability. We could
     // choose a very narrow (e.g., 1-hour) window to reduce vulnerability to
     // attacks using captured CSRF tokens, but it's also more likely that real
     // users will be affected by this, e.g. if they close their laptop for an
     // hour, open it back up, and try to submit a form before the CSRF refresh
     // can kick in. Since the user experience of submitting a form with expired
     // CSRF is often quite bad (you basically lose data, or it's a big pain to
     // recover at least) and I believe we gain little additional protection
     // by keeping the window very short (the overwhelming value here is in
     // preventing blind attacks, and most attacks which can capture CSRF tokens
     // can also just capture authentication information [sniffing networks]
     // or act as the user [xss]) the 7 hour default seems like a reasonable
     // balance. Other major platforms have much longer CSRF token lifetimes,
     // like Rails (session duration) and Django (forever), which suggests this
     // is a reasonable analysis.
     $csrf_window = 6;
 
     for ($ii = -$csrf_window; $ii <= 1; $ii++) {
       $valid = $this->getCSRFToken($ii);
       if ($token == $valid) {
         return true;
       }
     }
 
     return false;
   }
 
   private function generateToken($epoch, $frequency, $key, $len) {
     $time_block = floor($epoch / $frequency);
     $vec = $this->getPHID().$this->getPasswordHash().$key.$time_block;
     return substr(PhabricatorHash::digest($vec), 0, $len);
   }
 
   /**
    * Issue a new session key to this user. Phabricator supports different
    * types of sessions (like "web" and "conduit") and each session type may
    * have multiple concurrent sessions (this allows a user to be logged in on
    * multiple browsers at the same time, for instance).
    *
    * Note that this method is transport-agnostic and does not set cookies or
    * issue other types of tokens, it ONLY generates a new session key.
    *
    * You can configure the maximum number of concurrent sessions for various
    * session types in the Phabricator configuration.
    *
    * @param   string  Session type, like "web".
    * @return  string  Newly generated session key.
    */
   public function establishSession($session_type) {
     $conn_w = $this->establishConnection('w');
 
     if (strpos($session_type, '-') !== false) {
       throw new Exception("Session type must not contain hyphen ('-')!");
     }
 
     // We allow multiple sessions of the same type, so when a caller requests
     // a new session of type "web", we give them the first available session in
     // "web-1", "web-2", ..., "web-N", up to some configurable limit. If none
     // of these sessions is available, we overwrite the oldest session and
     // reissue a new one in its place.
 
     $session_limit = 1;
     switch ($session_type) {
       case 'web':
         $session_limit = PhabricatorEnv::getEnvConfig('auth.sessions.web');
         break;
       case 'conduit':
         $session_limit = PhabricatorEnv::getEnvConfig('auth.sessions.conduit');
         break;
       default:
         throw new Exception("Unknown session type '{$session_type}'!");
     }
 
     $session_limit = (int)$session_limit;
     if ($session_limit <= 0) {
       throw new Exception(
         "Session limit for '{$session_type}' must be at least 1!");
     }
 
     // NOTE: Session establishment is sensitive to race conditions, as when
     // piping `arc` to `arc`:
     //
     //   arc export ... | arc paste ...
     //
     // To avoid this, we overwrite an old session only if it hasn't been
     // re-established since we read it.
 
     // Consume entropy to generate a new session key, forestalling the eventual
     // heat death of the universe.
     $session_key = Filesystem::readRandomCharacters(40);
 
     // Load all the currently active sessions.
     $sessions = queryfx_all(
       $conn_w,
       'SELECT type, sessionKey, sessionStart FROM %T
         WHERE userPHID = %s AND type LIKE %>',
       PhabricatorUser::SESSION_TABLE,
       $this->getPHID(),
       $session_type.'-');
     $sessions = ipull($sessions, null, 'type');
     $sessions = isort($sessions, 'sessionStart');
 
     $existing_sessions = array_keys($sessions);
 
     // UNGUARDED WRITES: Logging-in users don't have CSRF stuff yet.
     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
 
     $retries = 0;
     while (true) {
 
 
       // Choose which 'type' we'll actually establish, i.e. what number we're
       // going to append to the basic session type. To do this, just check all
       // the numbers sequentially until we find an available session.
       $establish_type = null;
       for ($ii = 1; $ii <= $session_limit; $ii++) {
         $try_type = $session_type.'-'.$ii;
         if (!in_array($try_type, $existing_sessions)) {
           $establish_type = $try_type;
           $expect_key = $session_key;
           $existing_sessions[] = $try_type;
 
           // Ensure the row exists so we can issue an update below. We don't
           // care if we race here or not.
           queryfx(
             $conn_w,
             'INSERT IGNORE INTO %T (userPHID, type, sessionKey, sessionStart)
               VALUES (%s, %s, %s, 0)',
             self::SESSION_TABLE,
             $this->getPHID(),
             $establish_type,
             $session_key);
           break;
         }
       }
 
       // If we didn't find an available session, choose the oldest session and
       // overwrite it.
       if (!$establish_type) {
         $oldest = reset($sessions);
         $establish_type = $oldest['type'];
         $expect_key = $oldest['sessionKey'];
       }
 
       // This is so that we'll only overwrite the session if it hasn't been
       // refreshed since we read it. If it has, the session key will be
       // different and we know we're racing other processes. Whichever one
       // won gets the session, we go back and try again.
 
       queryfx(
         $conn_w,
         'UPDATE %T SET sessionKey = %s, sessionStart = UNIX_TIMESTAMP()
           WHERE userPHID = %s AND type = %s AND sessionKey = %s',
         self::SESSION_TABLE,
         $session_key,
         $this->getPHID(),
         $establish_type,
         $expect_key);
 
       if ($conn_w->getAffectedRows()) {
         // The update worked, so the session is valid.
         break;
       } else {
         // We know this just got grabbed, so don't try it again.
         unset($sessions[$establish_type]);
       }
 
       if (++$retries > $session_limit) {
         throw new Exception("Failed to establish a session!");
       }
     }
 
     $log = PhabricatorUserLog::newLog(
       $this,
       $this,
       PhabricatorUserLog::ACTION_LOGIN);
     $log->setDetails(
       array(
         'session_type' => $session_type,
         'session_issued' => $establish_type,
       ));
     $log->setSession($session_key);
     $log->save();
 
     return $session_key;
   }
 
   public function destroySession($session_key) {
     $conn_w = $this->establishConnection('w');
     queryfx(
       $conn_w,
       'DELETE FROM %T WHERE userPHID = %s AND sessionKey = %s',
       self::SESSION_TABLE,
       $this->getPHID(),
       $session_key);
   }
 
   private function generateEmailToken($offset = 0) {
     return $this->generateToken(
       time() + ($offset * self::EMAIL_CYCLE_FREQUENCY),
       self::EMAIL_CYCLE_FREQUENCY,
       PhabricatorEnv::getEnvConfig('phabricator.csrf-key').$this->getEmail(),
       self::EMAIL_TOKEN_LENGTH);
   }
 
   public function validateEmailToken($token) {
     for ($ii = -1; $ii <= 1; $ii++) {
       $valid = $this->generateEmailToken($ii);
       if ($token == $valid) {
         return true;
       }
     }
     return false;
   }
 
   public function getEmailLoginURI() {
     $token = $this->generateEmailToken();
     $uri = PhabricatorEnv::getProductionURI('/login/etoken/'.$token.'/');
     $uri = new PhutilURI($uri);
     return $uri->alter('email', $this->getEmail());
   }
 
   public function loadPreferences() {
     if ($this->preferences) {
       return $this->preferences;
     }
 
     $preferences = id(new PhabricatorUserPreferences())->loadOneWhere(
       'userPHID = %s',
       $this->getPHID());
 
     if (!$preferences) {
       $preferences = new PhabricatorUserPreferences();
       $preferences->setUserPHID($this->getPHID());
 
       $default_dict = array(
         PhabricatorUserPreferences::PREFERENCE_TITLES => 'glyph',
         PhabricatorUserPreferences::PREFERENCE_EDITOR => '',
         PhabricatorUserPreferences::PREFERENCE_MONOSPACED => '');
 
       $preferences->setPreferences($default_dict);
     }
 
     $this->preferences = $preferences;
     return $preferences;
   }
 
   public function loadEditorLink($path, $line, $callsign) {
     $editor = $this->loadPreferences()->getPreference(
       PhabricatorUserPreferences::PREFERENCE_EDITOR);
     if ($editor) {
       return strtr($editor, array(
         '%%' => '%',
         '%f' => phutil_escape_uri($path),
         '%l' => phutil_escape_uri($line),
         '%r' => phutil_escape_uri($callsign),
       ));
     }
   }
 
   private static function tokenizeName($name) {
     if (function_exists('mb_strtolower')) {
       $name = mb_strtolower($name, 'UTF-8');
     } else {
       $name = strtolower($name);
     }
     $name = trim($name);
     if (!strlen($name)) {
       return array();
     }
     return preg_split('/\s+/', $name);
   }
 
   /**
    * Populate the nametoken table, which used to fetch typeahead results. When
    * a user types "linc", we want to match "Abraham Lincoln" from on-demand
    * typeahead sources. To do this, we need a separate table of name fragments.
    */
   public function updateNameTokens() {
     $tokens = array_merge(
       self::tokenizeName($this->getRealName()),
       self::tokenizeName($this->getUserName()));
     $tokens = array_unique($tokens);
     $table  = self::NAMETOKEN_TABLE;
     $conn_w = $this->establishConnection('w');
 
     $sql = array();
     foreach ($tokens as $token) {
       $sql[] = qsprintf(
         $conn_w,
         '(%d, %s)',
         $this->getID(),
         $token);
     }
 
     queryfx(
       $conn_w,
       'DELETE FROM %T WHERE userID = %d',
       $table,
       $this->getID());
     if ($sql) {
       queryfx(
         $conn_w,
         'INSERT INTO %T (userID, token) VALUES %Q',
         $table,
         implode(', ', $sql));
     }
   }
 
   public function sendWelcomeEmail(PhabricatorUser $admin) {
     $admin_username = $admin->getUserName();
     $admin_realname = $admin->getRealName();
     $user_username = $this->getUserName();
     $is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
 
     $base_uri = PhabricatorEnv::getProductionURI('/');
 
     $uri = $this->getEmailLoginURI();
     $body = <<<EOBODY
 Welcome to Phabricator!
 
 {$admin_username} ({$admin_realname}) has created an account for you.
 
   Username: {$user_username}
 
 To login to Phabricator, follow this link and set a password:
 
   {$uri}
 
 After you have set a password, you can login in the future by going here:
 
   {$base_uri}
 
 EOBODY;
 
     if (!$is_serious) {
       $body .= <<<EOBODY
 
 Love,
 Phabricator
 
 EOBODY;
     }
 
     $mail = id(new PhabricatorMetaMTAMail())
       ->addTos(array($this->getPHID()))
       ->setSubject('[Phabricator] Welcome to Phabricator')
       ->setBody($body)
       ->setFrom($admin->getPHID())
       ->saveAndSend();
   }
 
   public static function validateUsername($username) {
     return (bool)preg_match('/^[a-zA-Z0-9]+$/', $username);
   }
 
+  public static function getDefaultProfileImageURI() {
+    return celerity_get_resource_uri('/rsrc/image/avatar.png');
+  }
+
+  public function loadProfileImageURI() {
+    $src_phid = $this->getProfileImagePHID();
+
+    $file = id(new PhabricatorFile())->loadOneWhere('phid = %s', $src_phid);
+    if ($file) {
+      return $file->getBestURI();
+    }
+
+    return self::getDefaultProfileImageURI();
+  }
+
 }
diff --git a/src/applications/people/storage/user/__init__.php b/src/applications/people/storage/user/__init__.php
index 910e09c634..3201c0f2e1 100644
--- a/src/applications/people/storage/user/__init__.php
+++ b/src/applications/people/storage/user/__init__.php
@@ -1,28 +1,30 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'aphront/writeguard');
+phutil_require_module('phabricator', 'applications/files/storage/file');
 phutil_require_module('phabricator', 'applications/metamta/storage/mail');
 phutil_require_module('phabricator', 'applications/people/storage/base');
 phutil_require_module('phabricator', 'applications/people/storage/log');
 phutil_require_module('phabricator', 'applications/people/storage/preferences');
 phutil_require_module('phabricator', 'applications/phid/constants');
 phutil_require_module('phabricator', 'applications/phid/storage/phid');
 phutil_require_module('phabricator', 'applications/search/index/indexer/user');
+phutil_require_module('phabricator', 'infrastructure/celerity/api');
 phutil_require_module('phabricator', 'infrastructure/env');
 phutil_require_module('phabricator', 'infrastructure/util/hash');
 phutil_require_module('phabricator', 'storage/qsprintf');
 phutil_require_module('phabricator', 'storage/queryfx');
 
 phutil_require_module('phutil', 'filesystem');
 phutil_require_module('phutil', 'markup');
 phutil_require_module('phutil', 'parser/uri');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorUser.php');
diff --git a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php
index a50a106b4d..de1ca5f562 100644
--- a/src/applications/phid/handle/data/PhabricatorObjectHandleData.php
+++ b/src/applications/phid/handle/data/PhabricatorObjectHandleData.php
@@ -1,483 +1,486 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorObjectHandleData {
 
   private $phids;
 
   public function __construct(array $phids) {
     $this->phids = array_unique($phids);
   }
 
   public static function loadOneHandle($phid) {
     $handles = id(new PhabricatorObjectHandleData(array($phid)))->loadHandles();
     return $handles[$phid];
   }
 
   public function loadObjects() {
     $types = array();
     foreach ($this->phids as $phid) {
       $type = phid_get_type($phid);
       $types[$type][] = $phid;
     }
 
     $objects = array();
     foreach ($types as $type => $phids) {
       switch ($type) {
         case PhabricatorPHIDConstants::PHID_TYPE_USER:
           $user_dao = newv('PhabricatorUser', array());
           $users = $user_dao->loadAllWhere(
             'phid in (%Ls)',
             $phids);
           foreach ($users as $user) {
             $objects[$user->getPHID()] = $user;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
           $commit_dao = newv('PhabricatorRepositoryCommit', array());
           $commits = $commit_dao->loadAllWhere(
             'phid IN (%Ls)',
             $phids);
           $commit_data = array();
           if ($commits) {
             $data_dao = newv('PhabricatorRepositoryCommitData', array());
             $commit_data = $data_dao->loadAllWhere(
               'commitID IN (%Ld)',
               mpull($commits, 'getID'));
             $commit_data = mpull($commit_data, null, 'getCommitID');
           }
           foreach ($commits as $commit) {
             $data = idx($commit_data, $commit->getID());
             if ($data) {
               $commit->attachCommitData($data);
               $objects[$commit->getPHID()] = $commit;
             } else {
              // If we couldn't load the commit data, just act as though we
              // couldn't load the object at all so we don't load half an object.
             }
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_TASK:
           $task_dao = newv('ManiphestTask', array());
           $tasks = $task_dao->loadAllWhere(
             'phid IN (%Ls)',
             $phids);
           foreach ($tasks as $task) {
             $objects[$task->getPHID()] = $task;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_DREV:
           $revision_dao = newv('DifferentialRevision', array());
           $revisions = $revision_dao->loadAllWhere(
             'phid IN (%Ls)',
             $phids);
           foreach ($revisions as $revision) {
             $objects[$revision->getPHID()] = $revision;
           }
           break;
       }
     }
 
     return $objects;
   }
 
   public function loadHandles() {
 
     $types = phid_group_by_type($this->phids);
 
     $handles = array();
 
     $external_loaders = PhabricatorEnv::getEnvConfig('phid.external-loaders');
 
     foreach ($types as $type => $phids) {
       switch ($type) {
         case PhabricatorPHIDConstants::PHID_TYPE_MAGIC:
           // Black magic!
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             switch ($phid) {
               case ManiphestTaskOwner::OWNER_UP_FOR_GRABS:
                 $handle->setName('Up For Grabs');
                 $handle->setFullName('upforgrabs (Up For Grabs)');
                 $handle->setComplete(true);
                 break;
               case ManiphestTaskOwner::PROJECT_NO_PROJECT:
                 $handle->setName('No Project');
                 $handle->setFullName('noproject (No Project)');
                 $handle->setComplete(true);
                 break;
               default:
                 $handle->setName('Foul Magicks');
                 break;
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_USER:
           $class = 'PhabricatorUser';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $users = $object->loadAllWhere('phid IN (%Ls)', $phids);
           $users = mpull($users, null, 'getPHID');
 
           $image_phids = mpull($users, 'getProfileImagePHID');
           $image_phids = array_unique(array_filter($image_phids));
 
           $images = array();
           if ($image_phids) {
             $images = id(new PhabricatorFile())->loadAllWhere(
               'phid IN (%Ls)',
               $image_phids);
             $images = mpull($images, 'getBestURI', 'getPHID');
           }
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($users[$phid])) {
               $handle->setName('Unknown User');
             } else {
               $user = $users[$phid];
               $handle->setName($user->getUsername());
               $handle->setURI('/p/'.$user->getUsername().'/');
               $handle->setEmail($user->getEmail());
               $handle->setFullName(
                 $user->getUsername().' ('.$user->getRealName().')');
               $handle->setAlternateID($user->getID());
               $handle->setComplete(true);
               $handle->setDisabled($user->getIsDisabled());
 
               $img_uri = idx($images, $user->getProfileImagePHID());
               if ($img_uri) {
                 $handle->setImageURI($img_uri);
+              } else {
+                $handle->setImageURI(
+                  PhabricatorUser::getDefaultProfileImageURI());
               }
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_MLST:
           $class = 'PhabricatorMetaMTAMailingList';
 
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $lists = $object->loadAllWhere('phid IN (%Ls)', $phids);
           $lists = mpull($lists, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($lists[$phid])) {
               $handle->setName('Unknown Mailing List');
             } else {
               $list = $lists[$phid];
               $handle->setEmail($list->getEmail());
               $handle->setName($list->getName());
               $handle->setURI($list->getURI());
               $handle->setFullName($list->getName());
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_DREV:
           $class = 'DifferentialRevision';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $revs = $object->loadAllWhere('phid in (%Ls)', $phids);
           $revs = mpull($revs, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($revs[$phid])) {
               $handle->setName('Unknown Revision');
             } else {
               $rev = $revs[$phid];
               $handle->setName($rev->getTitle());
               $handle->setURI('/D'.$rev->getID());
               $handle->setFullName('D'.$rev->getID().': '.$rev->getTitle());
               $handle->setComplete(true);
 
               $status = $rev->getStatus();
               if (($status == ArcanistDifferentialRevisionStatus::CLOSED) ||
                   ($status == ArcanistDifferentialRevisionStatus::ABANDONED)) {
                 $closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
                 $handle->setStatus($closed);
               }
 
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_CMIT:
           $class = 'PhabricatorRepositoryCommit';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $commits = $object->loadAllWhere('phid in (%Ls)', $phids);
           $commits = mpull($commits, null, 'getPHID');
 
           $repository_ids = array();
           $callsigns = array();
           if ($commits) {
             $repository_ids = mpull($commits, 'getRepositoryID');
             $repositories = id(new PhabricatorRepository())->loadAllWhere(
               'id in (%Ld)', array_unique($repository_ids));
             $callsigns = mpull($repositories, 'getCallsign');
           }
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($commits[$phid]) ||
                 !isset($callsigns[$repository_ids[$phid]])) {
               $handle->setName('Unknown Commit');
             } else {
               $commit = $commits[$phid];
               $callsign = $callsigns[$repository_ids[$phid]];
               $repository = $repositories[$repository_ids[$phid]];
               $commit_identifier = $commit->getCommitIdentifier();
 
               // In case where the repository for the commit was deleted,
               // we don't have have info about the repository anymore.
               if ($repository) {
                 $name = $repository->formatCommitName($commit_identifier);
                 $handle->setName($name);
               } else {
                 $handle->setName('Commit '.'r'.$callsign.$commit_identifier);
               }
 
               $handle->setURI('/r'.$callsign.$commit_identifier);
               $handle->setFullName('r'.$callsign.$commit_identifier);
               $handle->setTimestamp($commit->getEpoch());
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_TASK:
           $class = 'ManiphestTask';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $tasks = $object->loadAllWhere('phid in (%Ls)', $phids);
           $tasks = mpull($tasks, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($tasks[$phid])) {
               $handle->setName('Unknown Revision');
             } else {
               $task = $tasks[$phid];
               $handle->setName($task->getTitle());
               $handle->setURI('/T'.$task->getID());
               $handle->setFullName('T'.$task->getID().': '.$task->getTitle());
               $handle->setComplete(true);
               $handle->setAlternateID($task->getID());
               if ($task->getStatus() != ManiphestTaskStatus::STATUS_OPEN) {
                 $closed = PhabricatorObjectHandleStatus::STATUS_CLOSED;
                 $handle->setStatus($closed);
               }
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_FILE:
           $class = 'PhabricatorFile';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $files = $object->loadAllWhere('phid IN (%Ls)', $phids);
           $files = mpull($files, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($files[$phid])) {
               $handle->setName('Unknown File');
             } else {
               $file = $files[$phid];
               $handle->setName($file->getName());
               $handle->setURI($file->getBestURI());
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_PROJ:
           $class = 'PhabricatorProject';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $projects = $object->loadAllWhere('phid IN (%Ls)', $phids);
           $projects = mpull($projects, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($projects[$phid])) {
               $handle->setName('Unknown Project');
             } else {
               $project = $projects[$phid];
               $handle->setName($project->getName());
               $handle->setURI('/project/view/'.$project->getID().'/');
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_REPO:
           $class = 'PhabricatorRepository';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $repositories = $object->loadAllWhere('phid in (%Ls)', $phids);
           $repositories = mpull($repositories, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($repositories[$phid])) {
               $handle->setName('Unknown Repository');
             } else {
               $repository = $repositories[$phid];
               $handle->setName($repository->getCallsign());
               $handle->setURI('/diffusion/'.$repository->getCallsign().'/');
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_OPKG:
           $class = 'PhabricatorOwnersPackage';
           PhutilSymbolLoader::loadClass($class);
           $object = newv($class, array());
 
           $packages = $object->loadAllWhere('phid in (%Ls)', $phids);
           $packages = mpull($packages, null, 'getPHID');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($packages[$phid])) {
               $handle->setName('Unknown Package');
             } else {
               $package = $packages[$phid];
               $handle->setName($package->getName());
               $handle->setURI('/owners/package/'.$package->getID().'/');
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_APRJ:
           $project_dao = newv('PhabricatorRepositoryArcanistProject', array());
 
           $projects = $project_dao->loadAllWhere(
             'phid IN (%Ls)',
             $phids);
           $projects = mpull($projects, null, 'getPHID');
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($projects[$phid])) {
               $handle->setName('Unknown Arcanist Project');
             } else {
               $project = $projects[$phid];
               $handle->setName($project->getName());
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         case PhabricatorPHIDConstants::PHID_TYPE_WIKI:
           $document_dao = newv('PhrictionDocument', array());
           $content_dao  = newv('PhrictionContent', array());
 
           $conn = $document_dao->establishConnection('r');
           $documents = queryfx_all(
             $conn,
             'SELECT * FROM %T document JOIN %T content
               ON document.contentID = content.id
               WHERE document.phid IN (%Ls)',
               $document_dao->getTableName(),
               $content_dao->getTableName(),
               $phids);
           $documents = ipull($documents, null, 'phid');
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setPHID($phid);
             $handle->setType($type);
             if (empty($documents[$phid])) {
               $handle->setName('Unknown Document');
             } else {
               $info = $documents[$phid];
               $handle->setName($info['title']);
               $handle->setURI(PhrictionDocument::getSlugURI($info['slug']));
               $handle->setComplete(true);
             }
             $handles[$phid] = $handle;
           }
           break;
         default:
           $loader = null;
           if (isset($external_loaders[$type])) {
             $loader = $external_loaders[$type];
           } else if (isset($external_loaders['*'])) {
             $loader = $external_loaders['*'];
           }
 
           if ($loader) {
             PhutilSymbolLoader::loadClass($loader);
             $object = newv($loader, array());
             $handles += $object->loadHandles($phids);
             break;
           }
 
           foreach ($phids as $phid) {
             $handle = new PhabricatorObjectHandle();
             $handle->setType($type);
             $handle->setPHID($phid);
             $handle->setName('Unknown Object');
             $handle->setFullName('An Unknown Object');
             $handles[$phid] = $handle;
           }
           break;
       }
     }
 
     return $handles;
   }
 }
diff --git a/src/applications/phid/handle/data/__init__.php b/src/applications/phid/handle/data/__init__.php
index 3cfb40dbf3..c2df9169cd 100644
--- a/src/applications/phid/handle/data/__init__.php
+++ b/src/applications/phid/handle/data/__init__.php
@@ -1,27 +1,28 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('arcanist', 'differential/constants/revisionstatus');
 
 phutil_require_module('phabricator', 'applications/files/storage/file');
 phutil_require_module('phabricator', 'applications/maniphest/constants/owner');
 phutil_require_module('phabricator', 'applications/maniphest/constants/status');
+phutil_require_module('phabricator', 'applications/people/storage/user');
 phutil_require_module('phabricator', 'applications/phid/constants');
 phutil_require_module('phabricator', 'applications/phid/handle');
 phutil_require_module('phabricator', 'applications/phid/handle/const/status');
 phutil_require_module('phabricator', 'applications/phid/utils');
 phutil_require_module('phabricator', 'applications/phriction/storage/document');
 phutil_require_module('phabricator', 'applications/repository/storage/repository');
 phutil_require_module('phabricator', 'infrastructure/env');
 phutil_require_module('phabricator', 'storage/queryfx');
 
 phutil_require_module('phutil', 'symbols');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorObjectHandleData.php');
diff --git a/src/applications/project/controller/profile/PhabricatorProjectProfileController.php b/src/applications/project/controller/profile/PhabricatorProjectProfileController.php
index 22c03f7a08..9a7528810d 100644
--- a/src/applications/project/controller/profile/PhabricatorProjectProfileController.php
+++ b/src/applications/project/controller/profile/PhabricatorProjectProfileController.php
@@ -1,381 +1,381 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorProjectProfileController
   extends PhabricatorProjectController {
 
   private $id;
   private $page;
 
   public function willProcessRequest(array $data) {
     $this->id = idx($data, 'id');
     $this->page = idx($data, 'page');
   }
 
   public function processRequest() {
     $request = $this->getRequest();
     $user = $request->getUser();
 
     $project = id(new PhabricatorProject())->load($this->id);
     if (!$project) {
       return new Aphront404Response();
     }
     $profile = $project->loadProfile();
     if (!$profile) {
       $profile = new PhabricatorProjectProfile();
     }
 
     $src_phid = $profile->getProfileImagePHID();
     if (!$src_phid) {
       $src_phid = $user->getProfileImagePHID();
     }
     $file = id(new PhabricatorFile())->loadOneWhere('phid = %s',
                                                     $src_phid);
     if ($file) {
       $picture = $file->getBestURI();
     } else {
-      $picture = null;
+      $picture = PhabricatorUser::getDefaultProfileImageURI();
     }
 
     $members = mpull($project->loadAffiliations(), null, 'getUserPHID');
 
     $nav_view = new AphrontSideNavFilterView();
     $uri = new PhutilURI('/project/view/'.$project->getID().'/');
     $nav_view->setBaseURI($uri);
 
     $external_arrow = "\xE2\x86\x97";
     $tasks_uri = '/maniphest/view/all/?projects='.$project->getPHID();
     $slug = PhabricatorSlug::normalize($project->getName());
     $phriction_uri = '/w/projects/'.$slug;
 
     $edit_uri = '/project/edit/'.$project->getID().'/';
 
     $nav_view->addFilter('dashboard', 'Dashboard');
     $nav_view->addSpacer();
     $nav_view->addFilter('feed', 'Feed');
     $nav_view->addFilter(null, 'Tasks '.$external_arrow, $tasks_uri);
     $nav_view->addFilter(null, 'Wiki '.$external_arrow, $phriction_uri);
     $nav_view->addFilter('people', 'People');
     $nav_view->addFilter('about', 'About');
     $nav_view->addSpacer();
     $nav_view->addFilter(null, "Edit Project\xE2\x80\xA6", $edit_uri);
 
     $this->page = $nav_view->selectFilter($this->page, 'dashboard');
 
 
     require_celerity_resource('phabricator-profile-css');
     switch ($this->page) {
       case 'dashboard':
         $content = $this->renderTasksPage($project, $profile);
 
         $query = new PhabricatorFeedQuery();
         $query->setFilterPHIDs(
           array(
             $project->getPHID(),
           ));
         $stories = $query->execute();
 
         $content .= $this->renderStories($stories);
         break;
       case 'about':
         $content = $this->renderAboutPage($project, $profile);
         break;
       case 'people':
         $content = $this->renderPeoplePage($project, $profile);
         break;
       case 'feed':
         $content = $this->renderFeedPage($project, $profile);
         break;
       default:
         throw new Exception("Unimplemented filter '{$this->page}'.");
     }
 
     $content = '<div style="padding: 1em;">'.$content.'</div>';
     $nav_view->appendChild($content);
 
     $header = new PhabricatorProfileHeaderView();
     $header->setName($project->getName());
     $header->setDescription(
       phutil_utf8_shorten($profile->getBlurb(), 1024));
     $header->setProfilePicture($picture);
 
     $action = null;
     if (empty($members[$user->getPHID()])) {
       $action = phabricator_render_form(
         $user,
         array(
           'action' => '/project/update/'.$project->getID().'/join/',
           'method' => 'post',
         ),
         phutil_render_tag(
           'button',
           array(
             'class' => 'green',
           ),
           'Join Project'));
     } else {
       $action = javelin_render_tag(
         'a',
         array(
           'href'  => '/project/update/'.$project->getID().'/leave/',
           'sigil' => 'workflow',
           'class' => 'grey button',
         ),
         'Leave Project...');
     }
 
     $header->addAction($action);
 
     $header->appendChild($nav_view);
 
     return $this->buildStandardPageResponse(
       $header,
       array(
         'title' => $project->getName().' Project',
       ));
   }
 
   private function renderAboutPage(
     PhabricatorProject $project,
     PhabricatorProjectProfile $profile) {
 
     $viewer = $this->getRequest()->getUser();
 
     $blurb = $profile->getBlurb();
     $blurb = phutil_escape_html($blurb);
     $blurb = str_replace("\n", '<br />', $blurb);
 
     $phids = array_merge(
       array($project->getAuthorPHID()),
       $project->getSubprojectPHIDs()
     );
     $phids = array_unique($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))
       ->loadHandles();
 
     $timestamp = phabricator_datetime($project->getDateCreated(), $viewer);
 
     $about =
       '<div class="phabricator-profile-info-group">
         <h1 class="phabricator-profile-info-header">About</h1>
         <div class="phabricator-profile-info-pane">
           <table class="phabricator-profile-info-table">
             <tr>
               <th>Creator</th>
               <td>'.$handles[$project->getAuthorPHID()]->renderLink().'</td>
             </tr>
             <tr>
               <th>Created</th>
               <td>'.$timestamp.'</td>
             </tr>
             <tr>
               <th>PHID</th>
               <td>'.phutil_escape_html($project->getPHID()).'</td>
             </tr>
             <tr>
               <th>Blurb</th>
               <td>'.$blurb.'</td>
             </tr>
           </table>
         </div>
       </div>';
 
     if ($project->getSubprojectPHIDs()) {
       $table = $this->renderSubprojectTable(
         $handles,
         $project->getSubprojectPHIDs());
       $subproject_list = $table->render();
     } else {
       $subproject_list = '<p><em>No subprojects.</em></p>';
     }
 
     $about .=
       '<div class="phabricator-profile-info-group">'.
         '<h1 class="phabricator-profile-info-header">Subprojects</h1>'.
         '<div class="phabricator-profile-info-pane">'.
           $subproject_list.
         '</div>'.
       '</div>';
 
     return $about;
   }
 
   private function renderPeoplePage(
     PhabricatorProject $project,
     PhabricatorProjectProfile $profile) {
 
     $affiliations = $project->loadAffiliations();
 
     $phids = mpull($affiliations, 'getUserPHID');
     $handles = id(new PhabricatorObjectHandleData($phids))
       ->loadHandles();
 
     $affiliated = array();
     foreach ($affiliations as $affiliation) {
       $user = $handles[$affiliation->getUserPHID()]->renderLink();
       $role = phutil_escape_html($affiliation->getRole());
       $affiliated[] = '<li>'.$user.' &mdash; '.$role.'</li>';
     }
 
     if ($affiliated) {
       $affiliated = '<ul>'.implode("\n", $affiliated).'</ul>';
     } else {
       $affiliated = '<p><em>No one is affiliated with this project.</em></p>';
     }
 
     return
       '<div class="phabricator-profile-info-group">'.
         '<h1 class="phabricator-profile-info-header">People</h1>'.
         '<div class="phabricator-profile-info-pane">'.
          $affiliated.
         '</div>'.
       '</div>';
   }
 
   private function renderFeedPage(
     PhabricatorProject $project,
     PhabricatorProjectProfile $profile) {
 
     $query = new PhabricatorFeedQuery();
     $query->setFilterPHIDs(array($project->getPHID()));
     $stories = $query->execute();
 
     if (!$stories) {
       return 'There are no stories about this project.';
     }
 
     $query = new PhabricatorFeedQuery();
     $query->setFilterPHIDs(
       array(
         $project->getPHID(),
       ));
     $stories = $query->execute();
 
     return $this->renderStories($stories);
   }
 
   private function renderStories(array $stories) {
     assert_instances_of($stories, 'PhabricatorFeedStory');
 
     $builder = new PhabricatorFeedBuilder($stories);
     $builder->setUser($this->getRequest()->getUser());
     $view = $builder->buildView();
 
     return
       '<div class="phabricator-profile-info-group">'.
         '<h1 class="phabricator-profile-info-header">Activity Feed</h1>'.
         '<div class="phabricator-profile-info-pane">'.
          $view->render().
         '</div>'.
       '</div>';
   }
 
 
   private function renderTasksPage(
     PhabricatorProject $project,
     PhabricatorProjectProfile $profile) {
 
     $query = id(new ManiphestTaskQuery())
       ->withProjects(array($project->getPHID()))
       ->withStatus(ManiphestTaskQuery::STATUS_OPEN)
       ->setOrderBy(ManiphestTaskQuery::ORDER_PRIORITY)
       ->setLimit(10)
       ->setCalculateRows(true);
     $tasks = $query->execute();
     $count = $query->getRowCount();
 
     $phids = mpull($tasks, 'getOwnerPHID');
     $phids = array_filter($phids);
     $handles = id(new PhabricatorObjectHandleData($phids))
       ->loadHandles();
 
     $task_views = array();
     foreach ($tasks as $task) {
       $view = id(new ManiphestTaskSummaryView())
         ->setTask($task)
         ->setHandles($handles)
         ->setUser($this->getRequest()->getUser());
       $task_views[] = $view->render();
     }
 
     if (empty($tasks)) {
       $task_views = '<em>No open tasks.</em>';
     } else {
       $task_views = implode('', $task_views);
     }
 
     $open = number_format($count);
 
     $more_link = phutil_render_tag(
       'a',
       array(
         'href' => '/maniphest/view/all/?projects='.$project->getPHID(),
       ),
       "View All Open Tasks \xC2\xBB");
 
     $content =
       '<div class="phabricator-profile-info-group">
         <h1 class="phabricator-profile-info-header">'.
           "Open Tasks ({$open})".
         '</h1>'.
         '<div class="phabricator-profile-info-pane">'.
           $task_views.
           '<div class="phabricator-profile-info-pane-more-link">'.
             $more_link.
           '</div>'.
         '</div>
       </div>';
 
     return $content;
   }
 
   private function renderSubprojectTable(
     PhabricatorObjectHandleData $handles,
     $subprojects_phids) {
 
     $rows = array();
     foreach ($subprojects_phids as $subproject_phid) {
       $phid = $handles[$subproject_phid]->getPHID();
 
       $rows[] = array(
         phutil_escape_html($handles[$phid]->getFullName()),
         phutil_render_tag(
           'a',
           array(
             'class' => 'small grey button',
             'href' => $handles[$phid]->getURI(),
           ),
           'View Project Profile'),
       );
     }
 
     $table = new AphrontTableView($rows);
      $table->setHeaders(
        array(
          'Name',
          '',
        ));
      $table->setColumnClasses(
        array(
          'pri',
          'action right',
        ));
 
     return $table;
   }
 }
diff --git a/src/applications/project/controller/profile/__init__.php b/src/applications/project/controller/profile/__init__.php
index 8447952294..88f55e9312 100644
--- a/src/applications/project/controller/profile/__init__.php
+++ b/src/applications/project/controller/profile/__init__.php
@@ -1,32 +1,33 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'aphront/response/404');
 phutil_require_module('phabricator', 'applications/feed/builder/feed');
 phutil_require_module('phabricator', 'applications/feed/query');
 phutil_require_module('phabricator', 'applications/files/storage/file');
 phutil_require_module('phabricator', 'applications/maniphest/query');
 phutil_require_module('phabricator', 'applications/maniphest/view/tasksummary');
+phutil_require_module('phabricator', 'applications/people/storage/user');
 phutil_require_module('phabricator', 'applications/phid/handle/data');
 phutil_require_module('phabricator', 'applications/project/controller/base');
 phutil_require_module('phabricator', 'applications/project/storage/profile');
 phutil_require_module('phabricator', 'applications/project/storage/project');
 phutil_require_module('phabricator', 'infrastructure/celerity/api');
 phutil_require_module('phabricator', 'infrastructure/javelin/markup');
 phutil_require_module('phabricator', 'infrastructure/util/slug');
 phutil_require_module('phabricator', 'view/control/table');
 phutil_require_module('phabricator', 'view/layout/profileheader');
 phutil_require_module('phabricator', 'view/layout/sidenavfilter');
 phutil_require_module('phabricator', 'view/utils');
 
 phutil_require_module('phutil', 'markup');
 phutil_require_module('phutil', 'parser/uri');
 phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorProjectProfileController.php');
diff --git a/src/applications/project/storage/profile/PhabricatorProjectProfile.php b/src/applications/project/storage/profile/PhabricatorProjectProfile.php
index f14d070138..2fc6d0403c 100644
--- a/src/applications/project/storage/profile/PhabricatorProjectProfile.php
+++ b/src/applications/project/storage/profile/PhabricatorProjectProfile.php
@@ -1,30 +1,25 @@
 <?php
 
 /*
  * Copyright 2012 Facebook, Inc.
  *
  * 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.
  */
 
 final class PhabricatorProjectProfile extends PhabricatorProjectDAO {
 
   protected $projectPHID;
   protected $blurb;
   protected $profileImagePHID;
 
-  public function getProfileImagePHID() {
-    return nonempty(
-        $this->profileImagePHID,
-        PhabricatorEnv::getEnvConfig('user.default-profile-image-phid'));
-  }
 }
diff --git a/src/applications/project/storage/profile/__init__.php b/src/applications/project/storage/profile/__init__.php
index 7049de11cc..da02c73032 100644
--- a/src/applications/project/storage/profile/__init__.php
+++ b/src/applications/project/storage/profile/__init__.php
@@ -1,15 +1,12 @@
 <?php
 /**
  * This file is automatically generated. Lint this module to rebuild it.
  * @generated
  */
 
 
 
 phutil_require_module('phabricator', 'applications/project/storage/base');
-phutil_require_module('phabricator', 'infrastructure/env');
-
-phutil_require_module('phutil', 'utils');
 
 
 phutil_require_source('PhabricatorProjectProfile.php');
diff --git a/webroot/rsrc/image/avatar.png b/webroot/rsrc/image/avatar.png
new file mode 100644
index 0000000000..755d19cd2e
Binary files /dev/null and b/webroot/rsrc/image/avatar.png differ