diff --git a/conf/default.conf.php b/conf/default.conf.php index f604a7a9c4..892dc6987d 100644 --- a/conf/default.conf.php +++ b/conf/default.conf.php @@ -1,806 +1,817 @@ 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', // -- 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', ), // -- MySQL --------------------------------------------------------------- // // 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, // -- 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 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, + // 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. 'metamta.re-prefix' => false, // -- 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, // -- 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', ), // 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 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, // 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, // 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/__phutil_library_map__.php b/src/__phutil_library_map__.php index 4e1aa1c113..6f3d9b5033 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -1,1604 +1,1606 @@ array( 'Aphront304Response' => 'aphront/response/304', 'Aphront400Response' => 'aphront/response/400', 'Aphront403Response' => 'aphront/response/403', 'Aphront404Response' => 'aphront/response/404', 'AphrontAjaxResponse' => 'aphront/response/ajax', 'AphrontApplicationConfiguration' => 'aphront/applicationconfiguration', 'AphrontAttachedFileView' => 'view/control/attachedfile', 'AphrontCSRFException' => 'aphront/exception/csrf', 'AphrontCalendarMonthView' => 'applications/calendar/view/month', 'AphrontContextBarView' => 'view/layout/contextbar', 'AphrontController' => 'aphront/controller', 'AphrontCrumbsView' => 'view/layout/crumbs', 'AphrontDatabaseConnection' => 'storage/connection/base', 'AphrontDatabaseTransactionState' => 'storage/transaction', 'AphrontDefaultApplicationConfiguration' => 'aphront/default/configuration', 'AphrontDefaultApplicationController' => 'aphront/default/controller', 'AphrontDialogResponse' => 'aphront/response/dialog', 'AphrontDialogView' => 'view/dialog', 'AphrontErrorView' => 'view/form/error', 'AphrontException' => 'aphront/exception/base', 'AphrontFilePreviewView' => 'view/layout/filepreview', 'AphrontFileResponse' => 'aphront/response/file', 'AphrontFormCheckboxControl' => 'view/form/control/checkbox', 'AphrontFormControl' => 'view/form/control/base', 'AphrontFormDividerControl' => 'view/form/control/divider', 'AphrontFormDragAndDropUploadControl' => 'view/form/control/draganddropupload', 'AphrontFormFileControl' => 'view/form/control/file', 'AphrontFormLayoutView' => 'view/form/layout', 'AphrontFormMarkupControl' => 'view/form/control/markup', 'AphrontFormPasswordControl' => 'view/form/control/password', 'AphrontFormRadioButtonControl' => 'view/form/control/radio', 'AphrontFormRecaptchaControl' => 'view/form/control/recaptcha', 'AphrontFormSelectControl' => 'view/form/control/select', 'AphrontFormStaticControl' => 'view/form/control/static', 'AphrontFormSubmitControl' => 'view/form/control/submit', 'AphrontFormTextAreaControl' => 'view/form/control/textarea', 'AphrontFormTextControl' => 'view/form/control/text', 'AphrontFormToggleButtonsControl' => 'view/form/control/togglebuttons', 'AphrontFormTokenizerControl' => 'view/form/control/tokenizer', 'AphrontFormView' => 'view/form/base', 'AphrontHTTPSink' => 'aphront/sink/base', 'AphrontHTTPSinkTestCase' => 'aphront/sink/base/__tests__', 'AphrontHeadsupActionListView' => 'view/layout/headsup/actionlist', 'AphrontHeadsupActionView' => 'view/layout/headsup/action', 'AphrontIsolatedDatabaseConnection' => 'storage/connection/isolated', 'AphrontIsolatedDatabaseConnectionTestCase' => 'storage/connection/isolated/__tests__', 'AphrontIsolatedHTTPSink' => 'aphront/sink/test', 'AphrontJSONResponse' => 'aphront/response/json', 'AphrontJavelinView' => 'view/javelin-view', 'AphrontKeyboardShortcutsAvailableView' => 'view/widget/keyboardshortcuts', 'AphrontListFilterView' => 'view/layout/listfilter', 'AphrontMiniPanelView' => 'view/layout/minipanel', 'AphrontMySQLDatabaseConnection' => 'storage/connection/mysql', 'AphrontMySQLDatabaseConnectionTestCase' => 'storage/connection/mysql/__tests__', 'AphrontNullView' => 'view/null', 'AphrontPHPHTTPSink' => 'aphront/sink/php', 'AphrontPageView' => 'view/page/base', 'AphrontPagerView' => 'view/control/pager', 'AphrontPanelView' => 'view/layout/panel', 'AphrontPlainTextResponse' => 'aphront/response/plaintext', 'AphrontQueryAccessDeniedException' => 'storage/exception/accessdenied', 'AphrontQueryConnectionException' => 'storage/exception/connection', 'AphrontQueryConnectionLostException' => 'storage/exception/connectionlost', 'AphrontQueryCountException' => 'storage/exception/count', 'AphrontQueryDuplicateKeyException' => 'storage/exception/duplicatekey', 'AphrontQueryException' => 'storage/exception/base', 'AphrontQueryObjectMissingException' => 'storage/exception/objectmissing', 'AphrontQueryParameterException' => 'storage/exception/parameter', 'AphrontQueryRecoverableException' => 'storage/exception/recoverable', 'AphrontRedirectException' => 'aphront/exception/redirect', 'AphrontRedirectResponse' => 'aphront/response/redirect', 'AphrontReloadResponse' => 'aphront/response/reload', 'AphrontRequest' => 'aphront/request', 'AphrontRequestFailureView' => 'view/page/failure', 'AphrontRequestTestCase' => 'aphront/request/__tests__', 'AphrontResponse' => 'aphront/response/base', 'AphrontScopedUnguardedWriteCapability' => 'aphront/writeguard/scopeguard', 'AphrontSideNavFilterView' => 'view/layout/sidenavfilter', 'AphrontSideNavView' => 'view/layout/sidenav', 'AphrontTableView' => 'view/control/table', 'AphrontTokenizerTemplateView' => 'view/control/tokenizer', 'AphrontTypeaheadTemplateView' => 'view/control/typeahead', 'AphrontURIMapper' => 'aphront/mapper', 'AphrontView' => 'view/base', 'AphrontWebpageResponse' => 'aphront/response/webpage', 'AphrontWriteGuard' => 'aphront/writeguard', 'CelerityAPI' => 'infrastructure/celerity/api', 'CelerityResourceController' => 'infrastructure/celerity/controller', 'CelerityResourceGraph' => 'infrastructure/celerity/graph', 'CelerityResourceMap' => 'infrastructure/celerity/map', 'CelerityStaticResourceResponse' => 'infrastructure/celerity/response', 'ConduitAPIMethod' => 'applications/conduit/method/base', 'ConduitAPIRequest' => 'applications/conduit/protocol/request', 'ConduitAPIResponse' => 'applications/conduit/protocol/response', 'ConduitAPI_arcanist_Method' => 'applications/conduit/method/arcanist/base', 'ConduitAPI_arcanist_projectinfo_Method' => 'applications/conduit/method/arcanist/projectinfo', 'ConduitAPI_chatlog_Method' => 'applications/conduit/method/chatlog/base', 'ConduitAPI_chatlog_query_Method' => 'applications/conduit/method/chatlog/query', 'ConduitAPI_chatlog_record_Method' => 'applications/conduit/method/chatlog/record', 'ConduitAPI_conduit_connect_Method' => 'applications/conduit/method/conduit/connect', 'ConduitAPI_conduit_getcertificate_Method' => 'applications/conduit/method/conduit/getcertificate', 'ConduitAPI_conduit_ping_Method' => 'applications/conduit/method/conduit/ping', 'ConduitAPI_daemon_launched_Method' => 'applications/conduit/method/daemon/launched', 'ConduitAPI_daemon_log_Method' => 'applications/conduit/method/daemon/log', 'ConduitAPI_differential_createcomment_Method' => 'applications/conduit/method/differential/createcomment', 'ConduitAPI_differential_creatediff_Method' => 'applications/conduit/method/differential/creatediff', 'ConduitAPI_differential_createrevision_Method' => 'applications/conduit/method/differential/createrevision', 'ConduitAPI_differential_find_Method' => 'applications/conduit/method/differential/find', 'ConduitAPI_differential_getalldiffs_Method' => 'applications/conduit/method/differential/getalldiffs', 'ConduitAPI_differential_getcommitmessage_Method' => 'applications/conduit/method/differential/getcommitmessage', 'ConduitAPI_differential_getcommitpaths_Method' => 'applications/conduit/method/differential/getcommitpaths', 'ConduitAPI_differential_getdiff_Method' => 'applications/conduit/method/differential/getdiff', 'ConduitAPI_differential_getrevision_Method' => 'applications/conduit/method/differential/getrevision', 'ConduitAPI_differential_getrevisioncomments_Method' => 'applications/conduit/method/differential/getrevisioncomments', 'ConduitAPI_differential_getrevisionfeedback_Method' => 'applications/conduit/method/differential/getrevisionfeedback', 'ConduitAPI_differential_markcommitted_Method' => 'applications/conduit/method/differential/markcommitted', 'ConduitAPI_differential_parsecommitmessage_Method' => 'applications/conduit/method/differential/parsecommitmessage', 'ConduitAPI_differential_query_Method' => 'applications/conduit/method/differential/query', 'ConduitAPI_differential_setdiffproperty_Method' => 'applications/conduit/method/differential/setdiffproperty', 'ConduitAPI_differential_updaterevision_Method' => 'applications/conduit/method/differential/updaterevision', 'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'applications/conduit/method/differential/updatetaskrevisionassoc', 'ConduitAPI_differential_updateunitresults_Method' => 'applications/conduit/method/differential/updateunitresults', 'ConduitAPI_diffusion_findsymbols_Method' => 'applications/conduit/method/diffusion/findsymbols', 'ConduitAPI_diffusion_getcommits_Method' => 'applications/conduit/method/diffusion/getcommits', 'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'applications/conduit/method/diffusion/getrecentcommitsbypath', 'ConduitAPI_feed_publish_Method' => 'applications/conduit/method/feed/publish', 'ConduitAPI_feed_query_Method' => 'applications/conduit/method/feed/query', 'ConduitAPI_file_download_Method' => 'applications/conduit/method/file/download', 'ConduitAPI_file_info_Method' => 'applications/conduit/method/file/info', 'ConduitAPI_file_upload_Method' => 'applications/conduit/method/file/upload', 'ConduitAPI_maniphest_Method' => 'applications/conduit/method/maniphest/base', 'ConduitAPI_maniphest_createtask_Method' => 'applications/conduit/method/maniphest/createtask', 'ConduitAPI_maniphest_find_Method' => 'applications/conduit/method/maniphest/find', 'ConduitAPI_maniphest_gettasktransactions_Method' => 'applications/conduit/method/maniphest/gettasktransactions', 'ConduitAPI_maniphest_info_Method' => 'applications/conduit/method/maniphest/info', 'ConduitAPI_maniphest_update_Method' => 'applications/conduit/method/maniphest/update', 'ConduitAPI_paste_Method' => 'applications/conduit/method/paste/base', 'ConduitAPI_paste_create_Method' => 'applications/conduit/method/paste/create', 'ConduitAPI_paste_info_Method' => 'applications/conduit/method/paste/info', 'ConduitAPI_path_getowners_Method' => 'applications/conduit/method/path/getowners', 'ConduitAPI_phid_Method' => 'applications/conduit/method/phid/base', 'ConduitAPI_phid_info_Method' => 'applications/conduit/method/phid/info', 'ConduitAPI_phid_query_Method' => 'applications/conduit/method/phid/query', 'ConduitAPI_phriction_Method' => 'applications/conduit/method/phriction/base', 'ConduitAPI_phriction_edit_Method' => 'applications/conduit/method/phriction/edit', 'ConduitAPI_phriction_history_Method' => 'applications/conduit/method/phriction/history', 'ConduitAPI_phriction_info_Method' => 'applications/conduit/method/phriction/info', 'ConduitAPI_project_Method' => 'applications/conduit/method/project/base', 'ConduitAPI_project_query_Method' => 'applications/conduit/method/project/query', 'ConduitAPI_remarkup_process_Method' => 'applications/conduit/method/remarkup/process', 'ConduitAPI_slowvote_info_Method' => 'applications/conduit/method/slowvote/info', 'ConduitAPI_user_Method' => 'applications/conduit/method/user/base', 'ConduitAPI_user_find_Method' => 'applications/conduit/method/user/find', 'ConduitAPI_user_info_Method' => 'applications/conduit/method/user/info', 'ConduitAPI_user_whoami_Method' => 'applications/conduit/method/user/whoami', 'ConduitException' => 'applications/conduit/protocol/exception', 'DarkConsole' => 'aphront/console/api', 'DarkConsoleConfigPlugin' => 'aphront/console/plugin/config', 'DarkConsoleController' => 'aphront/console/controller', 'DarkConsoleCore' => 'aphront/console/core', 'DarkConsoleErrorLogPlugin' => 'aphront/console/plugin/errorlog', 'DarkConsoleErrorLogPluginAPI' => 'aphront/console/plugin/errorlog/api', 'DarkConsoleEventPlugin' => 'aphront/console/plugin/event', 'DarkConsoleEventPluginAPI' => 'aphront/console/plugin/event/api', 'DarkConsolePlugin' => 'aphront/console/plugin/base', 'DarkConsoleRequestPlugin' => 'aphront/console/plugin/request', 'DarkConsoleServicesPlugin' => 'aphront/console/plugin/services', 'DarkConsoleXHProfPlugin' => 'aphront/console/plugin/xhprof', 'DarkConsoleXHProfPluginAPI' => 'aphront/console/plugin/xhprof/api', 'DatabaseConfigurationProvider' => 'applications/base/storage/configuration', 'DifferentialAction' => 'applications/differential/constants/action', 'DifferentialActionHasNoEffectException' => 'applications/differential/exception/noeffect', 'DifferentialAddCommentView' => 'applications/differential/view/addcomment', 'DifferentialAffectedPath' => 'applications/differential/storage/affectedpath', 'DifferentialApplyPatchFieldSpecification' => 'applications/differential/field/specification/applypatch', 'DifferentialArcanistProjectFieldSpecification' => 'applications/differential/field/specification/arcanistproject', 'DifferentialAuthorFieldSpecification' => 'applications/differential/field/specification/author', 'DifferentialAuxiliaryField' => 'applications/differential/storage/auxiliaryfield', 'DifferentialBlameRevisionFieldSpecification' => 'applications/differential/field/specification/blamerev', 'DifferentialBranchFieldSpecification' => 'applications/differential/field/specification/branch', 'DifferentialCCWelcomeMail' => 'applications/differential/mail/ccwelcome', 'DifferentialCCsFieldSpecification' => 'applications/differential/field/specification/ccs', 'DifferentialChangeType' => 'applications/differential/constants/changetype', 'DifferentialChangeset' => 'applications/differential/storage/changeset', 'DifferentialChangesetDetailView' => 'applications/differential/view/changesetdetailview', 'DifferentialChangesetListView' => 'applications/differential/view/changesetlistview', 'DifferentialChangesetParser' => 'applications/differential/parser/changeset', 'DifferentialChangesetViewController' => 'applications/differential/controller/changesetview', 'DifferentialComment' => 'applications/differential/storage/comment', 'DifferentialCommentEditor' => 'applications/differential/editor/comment', 'DifferentialCommentMail' => 'applications/differential/mail/comment', 'DifferentialCommentPreviewController' => 'applications/differential/controller/commentpreview', 'DifferentialCommentSaveController' => 'applications/differential/controller/commentsave', 'DifferentialCommitsFieldSpecification' => 'applications/differential/field/specification/commits', 'DifferentialController' => 'applications/differential/controller/base', 'DifferentialDAO' => 'applications/differential/storage/base', 'DifferentialDateCreatedFieldSpecification' => 'applications/differential/field/specification/datecreated', 'DifferentialDateModifiedFieldSpecification' => 'applications/differential/field/specification/datemodified', 'DifferentialDefaultFieldSelector' => 'applications/differential/field/selector/default', 'DifferentialDependenciesFieldSpecification' => 'applications/differential/field/specification/dependencies', 'DifferentialDiff' => 'applications/differential/storage/diff', 'DifferentialDiffContentMail' => 'applications/differential/mail/diffcontent', 'DifferentialDiffCreateController' => 'applications/differential/controller/diffcreate', 'DifferentialDiffProperty' => 'applications/differential/storage/diffproperty', 'DifferentialDiffTableOfContentsView' => 'applications/differential/view/difftableofcontents', 'DifferentialDiffViewController' => 'applications/differential/controller/diffview', 'DifferentialException' => 'applications/differential/exception/base', 'DifferentialExceptionMail' => 'applications/differential/mail/exception', 'DifferentialExportPatchFieldSpecification' => 'applications/differential/field/specification/exportpatch', 'DifferentialFieldDataNotAvailableException' => 'applications/differential/field/exception/notavailable', 'DifferentialFieldParseException' => 'applications/differential/field/exception/parse', 'DifferentialFieldSelector' => 'applications/differential/field/selector/base', 'DifferentialFieldSpecification' => 'applications/differential/field/specification/base', 'DifferentialFieldSpecificationIncompleteException' => 'applications/differential/field/exception/incomplete', 'DifferentialFieldValidationException' => 'applications/differential/field/exception/validation', 'DifferentialGitSVNIDFieldSpecification' => 'applications/differential/field/specification/gitsvnid', 'DifferentialHostFieldSpecification' => 'applications/differential/field/specification/host', 'DifferentialHunk' => 'applications/differential/storage/hunk', 'DifferentialInlineComment' => 'applications/differential/storage/inlinecomment', 'DifferentialInlineCommentEditController' => 'applications/differential/controller/inlinecommentedit', 'DifferentialInlineCommentPreviewController' => 'applications/differential/controller/inlinecommentpreview', 'DifferentialInlineCommentView' => 'applications/differential/view/inlinecomment', 'DifferentialLinesFieldSpecification' => 'applications/differential/field/specification/lines', 'DifferentialLintFieldSpecification' => 'applications/differential/field/specification/lint', 'DifferentialLintStatus' => 'applications/differential/constants/lintstatus', 'DifferentialLocalCommitsView' => 'applications/differential/view/localcommits', 'DifferentialMail' => 'applications/differential/mail/base', 'DifferentialManiphestTasksFieldSpecification' => 'applications/differential/field/specification/maniphesttasks', 'DifferentialNewDiffMail' => 'applications/differential/mail/newdiff', 'DifferentialPathFieldSpecification' => 'applications/differential/field/specification/path', 'DifferentialPrimaryPaneView' => 'applications/differential/view/primarypane', 'DifferentialReplyHandler' => 'applications/differential/replyhandler', 'DifferentialRevertPlanFieldSpecification' => 'applications/differential/field/specification/revertplan', 'DifferentialReviewRequestMail' => 'applications/differential/mail/reviewrequest', 'DifferentialReviewedByFieldSpecification' => 'applications/differential/field/specification/reviewedby', 'DifferentialReviewersFieldSpecification' => 'applications/differential/field/specification/reviewers', 'DifferentialRevision' => 'applications/differential/storage/revision', 'DifferentialRevisionCommentListView' => 'applications/differential/view/revisioncommentlist', 'DifferentialRevisionCommentView' => 'applications/differential/view/revisioncomment', 'DifferentialRevisionControlSystem' => 'applications/differential/constants/revisioncontrolsystem', 'DifferentialRevisionDetailRenderer' => 'applications/differential/controller/customrenderer', 'DifferentialRevisionDetailView' => 'applications/differential/view/revisiondetail', 'DifferentialRevisionEditController' => 'applications/differential/controller/revisionedit', 'DifferentialRevisionEditor' => 'applications/differential/editor/revision', 'DifferentialRevisionIDFieldParserTestCase' => 'applications/differential/field/specification/revisionid/__tests__', 'DifferentialRevisionIDFieldSpecification' => 'applications/differential/field/specification/revisionid', 'DifferentialRevisionListController' => 'applications/differential/controller/revisionlist', 'DifferentialRevisionListData' => 'applications/differential/data/revisionlist', 'DifferentialRevisionListView' => 'applications/differential/view/revisionlist', 'DifferentialRevisionQuery' => 'applications/differential/query/revision', 'DifferentialRevisionStatsController' => 'applications/differential/controller/revisionstats', 'DifferentialRevisionStatsView' => 'applications/differential/view/revisionstats', 'DifferentialRevisionStatusFieldSpecification' => 'applications/differential/field/specification/revisionstatus', 'DifferentialRevisionUpdateHistoryView' => 'applications/differential/view/revisionupdatehistory', 'DifferentialRevisionViewController' => 'applications/differential/controller/revisionview', 'DifferentialSubscribeController' => 'applications/differential/controller/subscribe', 'DifferentialSummaryFieldSpecification' => 'applications/differential/field/specification/summary', 'DifferentialTasksAttacher' => 'applications/differential/tasks', 'DifferentialTestPlanFieldSpecification' => 'applications/differential/field/specification/testplan', 'DifferentialTitleFieldSpecification' => 'applications/differential/field/specification/title', 'DifferentialUnitFieldSpecification' => 'applications/differential/field/specification/unit', 'DifferentialUnitStatus' => 'applications/differential/constants/unitstatus', 'DifferentialUnitTestResult' => 'applications/differential/constants/unittestresult', 'DiffusionBranchInformation' => 'applications/diffusion/data/branch', 'DiffusionBranchQuery' => 'applications/diffusion/query/branch/base', 'DiffusionBranchTableView' => 'applications/diffusion/view/branchtable', 'DiffusionBrowseController' => 'applications/diffusion/controller/browse', 'DiffusionBrowseFileController' => 'applications/diffusion/controller/file', 'DiffusionBrowseQuery' => 'applications/diffusion/query/browse/base', 'DiffusionBrowseTableView' => 'applications/diffusion/view/browsetable', 'DiffusionChangeController' => 'applications/diffusion/controller/change', 'DiffusionCommentListView' => 'applications/diffusion/view/commentlist', 'DiffusionCommentView' => 'applications/diffusion/view/comment', 'DiffusionCommitChangeTableView' => 'applications/diffusion/view/commitchangetable', 'DiffusionCommitController' => 'applications/diffusion/controller/commit', 'DiffusionCommitListController' => 'applications/diffusion/controller/commitlist', 'DiffusionContainsQuery' => 'applications/diffusion/query/contains/base', 'DiffusionController' => 'applications/diffusion/controller/base', 'DiffusionDiffController' => 'applications/diffusion/controller/diff', 'DiffusionDiffQuery' => 'applications/diffusion/query/diff/base', 'DiffusionEmptyResultView' => 'applications/diffusion/view/emptyresult', 'DiffusionFileContent' => 'applications/diffusion/data/filecontent', 'DiffusionFileContentQuery' => 'applications/diffusion/query/filecontent/base', 'DiffusionGitBranchQuery' => 'applications/diffusion/query/branch/git', 'DiffusionGitBranchQueryTestCase' => 'applications/diffusion/query/branch/git/__tests__', 'DiffusionGitBrowseQuery' => 'applications/diffusion/query/browse/git', 'DiffusionGitContainsQuery' => 'applications/diffusion/query/contains/git', 'DiffusionGitDiffQuery' => 'applications/diffusion/query/diff/git', 'DiffusionGitFileContentQuery' => 'applications/diffusion/query/filecontent/git', 'DiffusionGitHistoryQuery' => 'applications/diffusion/query/history/git', 'DiffusionGitLastModifiedQuery' => 'applications/diffusion/query/lastmodified/git', 'DiffusionGitRequest' => 'applications/diffusion/request/git', 'DiffusionHistoryController' => 'applications/diffusion/controller/history', 'DiffusionHistoryQuery' => 'applications/diffusion/query/history/base', 'DiffusionHistoryTableView' => 'applications/diffusion/view/historytable', 'DiffusionHomeController' => 'applications/diffusion/controller/home', 'DiffusionLastModifiedController' => 'applications/diffusion/controller/lastmodified', 'DiffusionLastModifiedQuery' => 'applications/diffusion/query/lastmodified/base', 'DiffusionMercurialBranchQuery' => 'applications/diffusion/query/branch/mercurial', 'DiffusionMercurialBrowseQuery' => 'applications/diffusion/query/browse/mercurial', 'DiffusionMercurialContainsQuery' => 'applications/diffusion/query/contains/mercurial', 'DiffusionMercurialDiffQuery' => 'applications/diffusion/query/diff/mercurial', 'DiffusionMercurialFileContentQuery' => 'applications/diffusion/query/filecontent/mercurial', 'DiffusionMercurialHistoryQuery' => 'applications/diffusion/query/history/mercurial', 'DiffusionMercurialLastModifiedQuery' => 'applications/diffusion/query/lastmodified/mercurial', 'DiffusionMercurialRequest' => 'applications/diffusion/request/mercurial', 'DiffusionPathChange' => 'applications/diffusion/data/pathchange', 'DiffusionPathChangeQuery' => 'applications/diffusion/query/pathchange/base', 'DiffusionPathCompleteController' => 'applications/diffusion/controller/pathcomplete', 'DiffusionPathIDQuery' => 'applications/diffusion/query/pathid/base', 'DiffusionPathQueryTestCase' => 'applications/diffusion/query/pathid/base/__tests__', 'DiffusionPathValidateController' => 'applications/diffusion/controller/pathvalidate', 'DiffusionQuery' => 'applications/diffusion/query/base', 'DiffusionRepositoryController' => 'applications/diffusion/controller/repository', 'DiffusionRepositoryPath' => 'applications/diffusion/data/repositorypath', 'DiffusionRequest' => 'applications/diffusion/request/base', 'DiffusionSVNContainsQuery' => 'applications/diffusion/query/contains/svn', 'DiffusionSvnBrowseQuery' => 'applications/diffusion/query/browse/svn', 'DiffusionSvnDiffQuery' => 'applications/diffusion/query/diff/svn', 'DiffusionSvnFileContentQuery' => 'applications/diffusion/query/filecontent/svn', 'DiffusionSvnHistoryQuery' => 'applications/diffusion/query/history/svn', 'DiffusionSvnLastModifiedQuery' => 'applications/diffusion/query/lastmodified/svn', 'DiffusionSvnRequest' => 'applications/diffusion/request/svn', 'DiffusionSymbolController' => 'applications/diffusion/controller/symbol', 'DiffusionSymbolQuery' => 'applications/diffusion/query/symbol', 'DiffusionView' => 'applications/diffusion/view/base', 'DrydockAllocator' => 'applications/drydock/allocator/resource', 'DrydockAllocatorWorker' => 'applications/drydock/allocator/worker', 'DrydockBlueprint' => 'applications/drydock/blueprint/base', 'DrydockCommandInterface' => 'applications/drydock/interface/command/base', 'DrydockConstants' => 'applications/drydock/constants/base', 'DrydockController' => 'applications/drydock/controller/base', 'DrydockDAO' => 'applications/drydock/storage/base', 'DrydockEC2HostBlueprint' => 'applications/drydock/blueprint/ec2host', 'DrydockInterface' => 'applications/drydock/interface/base', 'DrydockLease' => 'applications/drydock/storage/lease', 'DrydockLeaseListController' => 'applications/drydock/controller/leaselist', 'DrydockLeaseStatus' => 'applications/drydock/constants/leasestatus', 'DrydockLocalCommandInterface' => 'applications/drydock/interface/command/local', 'DrydockLocalHostBlueprint' => 'applications/drydock/blueprint/localhost', 'DrydockRemoteHostBlueprint' => 'applications/drydock/blueprint/remotehost', 'DrydockResource' => 'applications/drydock/storage/resource', 'DrydockResourceAllocateController' => 'applications/drydock/controller/resourceallocate', 'DrydockResourceListController' => 'applications/drydock/controller/resourcelist', 'DrydockResourceStatus' => 'applications/drydock/constants/resourcestatus', 'DrydockSSHCommandInterface' => 'applications/drydock/interface/command/ssh', 'HeraldAction' => 'applications/herald/storage/action', 'HeraldActionConfig' => 'applications/herald/config/action', 'HeraldAllRulesController' => 'applications/herald/controller/all', 'HeraldApplyTranscript' => 'applications/herald/storage/transcript/apply', 'HeraldCommitAdapter' => 'applications/herald/adapter/commit', 'HeraldCondition' => 'applications/herald/storage/condition', 'HeraldConditionConfig' => 'applications/herald/config/condition', 'HeraldConditionTranscript' => 'applications/herald/storage/transcript/condition', 'HeraldContentTypeConfig' => 'applications/herald/config/contenttype', 'HeraldController' => 'applications/herald/controller/base', 'HeraldDAO' => 'applications/herald/storage/base', 'HeraldDeleteController' => 'applications/herald/controller/delete', 'HeraldDifferentialRevisionAdapter' => 'applications/herald/adapter/differential', 'HeraldDryRunAdapter' => 'applications/herald/adapter/dryrun', 'HeraldEffect' => 'applications/herald/engine/effect', 'HeraldEngine' => 'applications/herald/engine/engine', 'HeraldFieldConfig' => 'applications/herald/config/field', 'HeraldHomeController' => 'applications/herald/controller/home', 'HeraldInvalidConditionException' => 'applications/herald/engine/engine/exception', 'HeraldInvalidFieldException' => 'applications/herald/engine/engine/exception', 'HeraldNewController' => 'applications/herald/controller/new', 'HeraldObjectAdapter' => 'applications/herald/adapter/base', 'HeraldObjectTranscript' => 'applications/herald/storage/transcript/object', 'HeraldRecursiveConditionsException' => 'applications/herald/engine/engine/exception', 'HeraldRepetitionPolicyConfig' => 'applications/herald/config/repetitionpolicy', 'HeraldRule' => 'applications/herald/storage/rule', 'HeraldRuleController' => 'applications/herald/controller/rule', 'HeraldRuleEdit' => 'applications/herald/storage/edithistory', 'HeraldRuleEditHistoryController' => 'applications/herald/controller/edithistory', 'HeraldRuleEditHistoryView' => 'applications/herald/view/edithistory', 'HeraldRuleListView' => 'applications/herald/view/rulelist', 'HeraldRuleTranscript' => 'applications/herald/storage/transcript/rule', 'HeraldRuleTypeConfig' => 'applications/herald/config/ruletype', 'HeraldTestConsoleController' => 'applications/herald/controller/test', 'HeraldTranscript' => 'applications/herald/storage/transcript/base', 'HeraldTranscriptController' => 'applications/herald/controller/transcript', 'HeraldTranscriptListController' => 'applications/herald/controller/transcriptlist', 'HeraldValueTypeConfig' => 'applications/herald/config/valuetype', 'Javelin' => 'infrastructure/javelin/api', 'JavelinReactorExample' => 'applications/uiexample/examples/reactor', 'JavelinViewExample' => 'applications/uiexample/examples/client', 'JavelinViewExampleServerView' => 'applications/uiexample/examples/client', 'LiskDAO' => 'storage/lisk/dao', 'LiskIsolationTestCase' => 'storage/lisk/dao/__tests__', 'LiskIsolationTestDAO' => 'storage/lisk/dao/__tests__', 'LiskIsolationTestDAOException' => 'storage/lisk/dao/__tests__', 'ManiphestAction' => 'applications/maniphest/constants/action', 'ManiphestAuxiliaryFieldDefaultSpecification' => 'applications/maniphest/auxiliaryfield/default', 'ManiphestAuxiliaryFieldSpecification' => 'applications/maniphest/auxiliaryfield/base', 'ManiphestAuxiliaryFieldTypeException' => 'applications/maniphest/auxiliaryfield/typeexception', 'ManiphestAuxiliaryFieldValidationException' => 'applications/maniphest/auxiliaryfield/validationexception', 'ManiphestBatchEditController' => 'applications/maniphest/controller/batch', 'ManiphestConstants' => 'applications/maniphest/constants/base', 'ManiphestController' => 'applications/maniphest/controller/base', 'ManiphestDAO' => 'applications/maniphest/storage/base', 'ManiphestDefaultTaskExtensions' => 'applications/maniphest/extensions/task', 'ManiphestReplyHandler' => 'applications/maniphest/replyhandler', 'ManiphestReportController' => 'applications/maniphest/controller/report', 'ManiphestTask' => 'applications/maniphest/storage/task', 'ManiphestTaskAuxiliaryStorage' => 'applications/maniphest/storage/auxiliary', 'ManiphestTaskDescriptionChangeController' => 'applications/maniphest/controller/descriptionchange', 'ManiphestTaskDescriptionDiffController' => 'applications/maniphest/controller/descriptiondiff', 'ManiphestTaskDescriptionPreviewController' => 'applications/maniphest/controller/descriptionpreview', 'ManiphestTaskDetailController' => 'applications/maniphest/controller/taskdetail', 'ManiphestTaskEditController' => 'applications/maniphest/controller/taskedit', 'ManiphestTaskExtensions' => 'applications/maniphest/extensions/base', 'ManiphestTaskListController' => 'applications/maniphest/controller/tasklist', 'ManiphestTaskListView' => 'applications/maniphest/view/tasklist', 'ManiphestTaskOwner' => 'applications/maniphest/constants/owner', 'ManiphestTaskPriority' => 'applications/maniphest/constants/priority', 'ManiphestTaskProject' => 'applications/maniphest/storage/taskproject', 'ManiphestTaskQuery' => 'applications/maniphest/query', 'ManiphestTaskStatus' => 'applications/maniphest/constants/status', 'ManiphestTaskSubscriber' => 'applications/maniphest/storage/subscriber', 'ManiphestTaskSummaryView' => 'applications/maniphest/view/tasksummary', 'ManiphestTransaction' => 'applications/maniphest/storage/transaction', 'ManiphestTransactionDetailView' => 'applications/maniphest/view/transactiondetail', 'ManiphestTransactionEditor' => 'applications/maniphest/editor/transaction', 'ManiphestTransactionListView' => 'applications/maniphest/view/transactionlist', 'ManiphestTransactionPreviewController' => 'applications/maniphest/controller/transactionpreview', 'ManiphestTransactionSaveController' => 'applications/maniphest/controller/transactionsave', 'ManiphestTransactionType' => 'applications/maniphest/constants/transactiontype', 'ManiphestView' => 'applications/maniphest/view/base', 'MetaMTAConstants' => 'applications/metamta/constants/base', 'MetaMTANotificationType' => 'applications/metamta/constants/notificationtype', 'Phabricator404Controller' => 'applications/base/controller/404', 'PhabricatorAuditActionConstants' => 'applications/audit/constants/action', 'PhabricatorAuditAddCommentController' => 'applications/audit/controller/addcomment', 'PhabricatorAuditComment' => 'applications/audit/storage/auditcomment', 'PhabricatorAuditCommentEditor' => 'applications/audit/editor/comment', 'PhabricatorAuditController' => 'applications/audit/controller/base', 'PhabricatorAuditDAO' => 'applications/audit/storage/base', 'PhabricatorAuditEditController' => 'applications/audit/controller/edit', 'PhabricatorAuditListController' => 'applications/audit/controller/list', 'PhabricatorAuditListView' => 'applications/audit/view/list', 'PhabricatorAuditQuery' => 'applications/audit/query/audit', + 'PhabricatorAuditReplyHandler' => 'applications/audit/replyhandler', 'PhabricatorAuditStatusConstants' => 'applications/audit/constants/status', 'PhabricatorAuthController' => 'applications/auth/controller/base', 'PhabricatorCalendarBrowseController' => 'applications/calendar/controller/browse', 'PhabricatorCalendarController' => 'applications/calendar/controller/base', 'PhabricatorChatLogChannelListController' => 'applications/chatlog/controller/channellist', 'PhabricatorChatLogChannelLogController' => 'applications/chatlog/controller/channellog', 'PhabricatorChatLogConstants' => 'applications/chatlog/constants/base', 'PhabricatorChatLogController' => 'applications/chatlog/controller/base', 'PhabricatorChatLogDAO' => 'applications/chatlog/storage/base', 'PhabricatorChatLogEvent' => 'applications/chatlog/storage/event', 'PhabricatorChatLogEventType' => 'applications/chatlog/constants/eventtype', 'PhabricatorChatLogQuery' => 'applications/chatlog/query', 'PhabricatorConduitAPIController' => 'applications/conduit/controller/api', 'PhabricatorConduitCertificateToken' => 'applications/conduit/storage/token', 'PhabricatorConduitConnectionLog' => 'applications/conduit/storage/connectionlog', 'PhabricatorConduitConsoleController' => 'applications/conduit/controller/console', 'PhabricatorConduitController' => 'applications/conduit/controller/base', 'PhabricatorConduitDAO' => 'applications/conduit/storage/base', 'PhabricatorConduitLogController' => 'applications/conduit/controller/log', 'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog', 'PhabricatorConduitTokenController' => 'applications/conduit/controller/token', 'PhabricatorContentSource' => 'applications/metamta/contentsource/source', 'PhabricatorContentSourceView' => 'applications/metamta/contentsource/view', 'PhabricatorController' => 'applications/base/controller/base', 'PhabricatorCountdownController' => 'applications/countdown/controller/base', 'PhabricatorCountdownDAO' => 'applications/countdown/storage/base', 'PhabricatorCountdownDeleteController' => 'applications/countdown/controller/delete', 'PhabricatorCountdownEditController' => 'applications/countdown/controller/edit', 'PhabricatorCountdownListController' => 'applications/countdown/controller/list', 'PhabricatorCountdownViewController' => 'applications/countdown/controller/view', 'PhabricatorDaemon' => 'infrastructure/daemon/base', 'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/combined', 'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console', 'PhabricatorDaemonControl' => 'infrastructure/daemon/control', 'PhabricatorDaemonController' => 'applications/daemon/controller/base', 'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/base', 'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/log', 'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/event', 'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/daemonlogevents', 'PhabricatorDaemonLogListController' => 'applications/daemon/controller/loglist', 'PhabricatorDaemonLogListView' => 'applications/daemon/view/daemonloglist', 'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/logview', 'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference', 'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline', 'PhabricatorDaemonTimelineEventController' => 'applications/daemon/controller/timelineevent', 'PhabricatorDefaultFileStorageEngineSelector' => 'applications/files/engineselector/default', 'PhabricatorDefaultSearchEngineSelector' => 'applications/search/selector/default', 'PhabricatorDifferenceEngine' => 'infrastructure/diff/engine', 'PhabricatorDirectoryCategory' => 'applications/directory/storage/category', 'PhabricatorDirectoryCategoryDeleteController' => 'applications/directory/controller/categorydelete', 'PhabricatorDirectoryCategoryEditController' => 'applications/directory/controller/categoryedit', 'PhabricatorDirectoryCategoryViewController' => 'applications/directory/controller/categoryview', 'PhabricatorDirectoryController' => 'applications/directory/controller/base', 'PhabricatorDirectoryDAO' => 'applications/directory/storage/base', 'PhabricatorDirectoryEditController' => 'applications/directory/controller/edit', 'PhabricatorDirectoryItem' => 'applications/directory/storage/item', 'PhabricatorDirectoryItemDeleteController' => 'applications/directory/controller/itemdelete', 'PhabricatorDirectoryItemEditController' => 'applications/directory/controller/itemedit', 'PhabricatorDirectoryMainController' => 'applications/directory/controller/main', 'PhabricatorDisabledUserController' => 'applications/auth/controller/disabled', 'PhabricatorDraft' => 'applications/draft/storage/draft', 'PhabricatorDraftDAO' => 'applications/draft/storage/base', 'PhabricatorEmailLoginController' => 'applications/auth/controller/email', 'PhabricatorEmailTokenController' => 'applications/auth/controller/emailtoken', 'PhabricatorEnv' => 'infrastructure/env', 'PhabricatorEnvTestCase' => 'infrastructure/env/__tests__', 'PhabricatorEvent' => 'infrastructure/events/event', 'PhabricatorEventEngine' => 'infrastructure/events/engine', 'PhabricatorEventType' => 'infrastructure/events/constant/type', 'PhabricatorFeedBuilder' => 'applications/feed/builder/feed', 'PhabricatorFeedConstants' => 'applications/feed/constants/base', 'PhabricatorFeedController' => 'applications/feed/controller/base', 'PhabricatorFeedDAO' => 'applications/feed/storage/base', 'PhabricatorFeedPublicStreamController' => 'applications/feed/controller/publicstream', 'PhabricatorFeedQuery' => 'applications/feed/query', 'PhabricatorFeedStory' => 'applications/feed/story/base', 'PhabricatorFeedStoryAudit' => 'applications/feed/story/audit', 'PhabricatorFeedStoryData' => 'applications/feed/storage/story', 'PhabricatorFeedStoryDifferential' => 'applications/feed/story/differential', 'PhabricatorFeedStoryManiphest' => 'applications/feed/story/maniphest', 'PhabricatorFeedStoryPhriction' => 'applications/feed/story/phriction', 'PhabricatorFeedStoryProject' => 'applications/feed/story/project', 'PhabricatorFeedStoryPublisher' => 'applications/feed/publisher', 'PhabricatorFeedStoryReference' => 'applications/feed/storage/storyreference', 'PhabricatorFeedStoryStatus' => 'applications/feed/story/status', 'PhabricatorFeedStoryTypeConstants' => 'applications/feed/constants/story', 'PhabricatorFeedStoryUnknown' => 'applications/feed/story/unknown', 'PhabricatorFeedStoryView' => 'applications/feed/view/story', 'PhabricatorFeedView' => 'applications/feed/view/base', 'PhabricatorFile' => 'applications/files/storage/file', 'PhabricatorFileController' => 'applications/files/controller/base', 'PhabricatorFileDAO' => 'applications/files/storage/base', 'PhabricatorFileDataController' => 'applications/files/controller/data', 'PhabricatorFileDeleteController' => 'applications/files/controller/delete', 'PhabricatorFileDropUploadController' => 'applications/files/controller/dropupload', 'PhabricatorFileImageMacro' => 'applications/files/storage/imagemacro', 'PhabricatorFileInfoController' => 'applications/files/controller/info', 'PhabricatorFileListController' => 'applications/files/controller/list', 'PhabricatorFileMacroDeleteController' => 'applications/files/controller/macrodelete', 'PhabricatorFileMacroEditController' => 'applications/files/controller/macroedit', 'PhabricatorFileMacroListController' => 'applications/files/controller/macrolist', 'PhabricatorFileProxyController' => 'applications/files/controller/proxy', 'PhabricatorFileProxyImage' => 'applications/files/storage/proxyimage', 'PhabricatorFileSideNavView' => 'applications/files/view/sidenav', 'PhabricatorFileStorageBlob' => 'applications/files/storage/storageblob', 'PhabricatorFileStorageEngine' => 'applications/files/engine/base', 'PhabricatorFileStorageEngineSelector' => 'applications/files/engineselector/base', 'PhabricatorFileTransformController' => 'applications/files/controller/transform', 'PhabricatorFileUploadController' => 'applications/files/controller/upload', 'PhabricatorFileUploadException' => 'applications/files/exception/upload', 'PhabricatorFileUploadView' => 'applications/files/view/upload', 'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/garbagecollector', 'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/goodfornothing', 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/selector', 'PhabricatorHash' => 'infrastructure/util/hash', 'PhabricatorHelpController' => 'applications/help/controller/base', 'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/keyboardshortcut', 'PhabricatorIRCBot' => 'infrastructure/daemon/irc/bot', 'PhabricatorIRCDifferentialNotificationHandler' => 'infrastructure/daemon/irc/handler/differentialnotification', 'PhabricatorIRCHandler' => 'infrastructure/daemon/irc/handler/base', 'PhabricatorIRCLogHandler' => 'infrastructure/daemon/irc/handler/log', 'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message', 'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname', 'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol', 'PhabricatorIRCWhatsNewHandler' => 'infrastructure/daemon/irc/handler/whatsnew', 'PhabricatorImageTransformer' => 'applications/files/transform', 'PhabricatorInfrastructureTestCase' => 'infrastructure/__tests__', 'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin', 'PhabricatorLintEngine' => 'infrastructure/lint/engine', 'PhabricatorLiskDAO' => 'applications/base/storage/lisk', 'PhabricatorLocalDiskFileStorageEngine' => 'applications/files/engine/localdisk', 'PhabricatorLocalTimeTestCase' => 'view/utils/__tests__', 'PhabricatorLoginController' => 'applications/auth/controller/login', 'PhabricatorLoginValidateController' => 'applications/auth/controller/validate', 'PhabricatorLogoutController' => 'applications/auth/controller/logout', 'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/base', 'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/amazonses', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/phpmailerlite', 'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/sendgrid', 'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/test', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/base', 'PhabricatorMarkupEngine' => 'applications/markup/engine', 'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/mail', 'PhabricatorMetaMTAController' => 'applications/metamta/controller/base', 'PhabricatorMetaMTADAO' => 'applications/metamta/storage/base', 'PhabricatorMetaMTADaemon' => 'applications/metamta/daemon/mta', 'PhabricatorMetaMTAEmailBodyParser' => 'applications/metamta/parser', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'applications/metamta/parser/__tests__', 'PhabricatorMetaMTAListController' => 'applications/metamta/controller/list', 'PhabricatorMetaMTAMail' => 'applications/metamta/storage/mail', 'PhabricatorMetaMTAMailTestCase' => 'applications/metamta/storage/mail/__tests__', 'PhabricatorMetaMTAMailingList' => 'applications/metamta/storage/mailinglist', 'PhabricatorMetaMTAMailingListEditController' => 'applications/metamta/controller/mailinglistedit', 'PhabricatorMetaMTAMailingListsController' => 'applications/metamta/controller/mailinglists', 'PhabricatorMetaMTAReceiveController' => 'applications/metamta/controller/receive', 'PhabricatorMetaMTAReceivedListController' => 'applications/metamta/controller/receivedlist', 'PhabricatorMetaMTAReceivedMail' => 'applications/metamta/storage/receivedmail', 'PhabricatorMetaMTASendController' => 'applications/metamta/controller/send', 'PhabricatorMetaMTASendGridReceiveController' => 'applications/metamta/controller/sendgridreceive', 'PhabricatorMetaMTAViewController' => 'applications/metamta/controller/view', 'PhabricatorMySQLFileStorageEngine' => 'applications/files/engine/mysql', 'PhabricatorOAuthClientAuthorization' => 'applications/oauthserver/storage/clientauthorization', 'PhabricatorOAuthClientAuthorizationBaseController' => 'applications/oauthserver/controller/clientauthorization/base', 'PhabricatorOAuthClientAuthorizationDeleteController' => 'applications/oauthserver/controller/clientauthorization/delete', 'PhabricatorOAuthClientAuthorizationEditController' => 'applications/oauthserver/controller/clientauthorization/edit', 'PhabricatorOAuthClientAuthorizationListController' => 'applications/oauthserver/controller/clientauthorization/list', 'PhabricatorOAuthClientBaseController' => 'applications/oauthserver/controller/client/base', 'PhabricatorOAuthClientDeleteController' => 'applications/oauthserver/controller/client/delete', 'PhabricatorOAuthClientEditController' => 'applications/oauthserver/controller/client/edit', 'PhabricatorOAuthClientListController' => 'applications/oauthserver/controller/client/list', 'PhabricatorOAuthClientViewController' => 'applications/oauthserver/controller/client/view', 'PhabricatorOAuthDefaultRegistrationController' => 'applications/auth/controller/oauthregistration/default', 'PhabricatorOAuthDiagnosticsController' => 'applications/auth/controller/oauthdiagnostics', 'PhabricatorOAuthFailureView' => 'applications/auth/view/oauthfailure', 'PhabricatorOAuthLoginController' => 'applications/auth/controller/oauth', 'PhabricatorOAuthProvider' => 'applications/auth/oauth/provider/base', 'PhabricatorOAuthProviderFacebook' => 'applications/auth/oauth/provider/facebook', 'PhabricatorOAuthProviderGitHub' => 'applications/auth/oauth/provider/github', 'PhabricatorOAuthProviderGoogle' => 'applications/auth/oauth/provider/google', 'PhabricatorOAuthProviderPhabricator' => 'applications/auth/oauth/provider/phabricator', 'PhabricatorOAuthRegistrationController' => 'applications/auth/controller/oauthregistration/base', 'PhabricatorOAuthResponse' => 'applications/oauthserver/response', 'PhabricatorOAuthServer' => 'applications/oauthserver/server', 'PhabricatorOAuthServerAccessToken' => 'applications/oauthserver/storage/accesstoken', 'PhabricatorOAuthServerAuthController' => 'applications/oauthserver/controller/auth', 'PhabricatorOAuthServerAuthorizationCode' => 'applications/oauthserver/storage/authorizationcode', 'PhabricatorOAuthServerClient' => 'applications/oauthserver/storage/client', 'PhabricatorOAuthServerController' => 'applications/oauthserver/controller/base', 'PhabricatorOAuthServerDAO' => 'applications/oauthserver/storage/base', 'PhabricatorOAuthServerScope' => 'applications/oauthserver/scope', 'PhabricatorOAuthServerTestController' => 'applications/oauthserver/controller/test', 'PhabricatorOAuthServerTokenController' => 'applications/oauthserver/controller/token', 'PhabricatorOAuthUnlinkController' => 'applications/auth/controller/unlink', 'PhabricatorObjectAttachmentEditor' => 'applications/search/editor/attach', 'PhabricatorObjectGraph' => 'applications/phid/graph', 'PhabricatorObjectHandle' => 'applications/phid/handle', 'PhabricatorObjectHandleConstants' => 'applications/phid/handle/const/base', 'PhabricatorObjectHandleData' => 'applications/phid/handle/data', 'PhabricatorObjectHandleStatus' => 'applications/phid/handle/const/status', 'PhabricatorObjectSelectorDialog' => 'view/control/objectselector', 'PhabricatorOwnerPathQuery' => 'applications/owners/query/path', 'PhabricatorOwnerRelatedListController' => 'applications/owners/controller/relatedlist', 'PhabricatorOwnersController' => 'applications/owners/controller/base', 'PhabricatorOwnersDAO' => 'applications/owners/storage/base', 'PhabricatorOwnersDeleteController' => 'applications/owners/controller/delete', 'PhabricatorOwnersDetailController' => 'applications/owners/controller/detail', 'PhabricatorOwnersEditController' => 'applications/owners/controller/edit', 'PhabricatorOwnersListController' => 'applications/owners/controller/list', 'PhabricatorOwnersOwner' => 'applications/owners/storage/owner', 'PhabricatorOwnersPackage' => 'applications/owners/storage/package', 'PhabricatorOwnersPackageCommitRelationship' => 'applications/owners/storage/packagecommitrelationship', 'PhabricatorOwnersPath' => 'applications/owners/storage/path', 'PhabricatorPHID' => 'applications/phid/storage/phid', 'PhabricatorPHIDConstants' => 'applications/phid/constants', 'PhabricatorPHIDController' => 'applications/phid/controller/base', 'PhabricatorPHIDDAO' => 'applications/phid/storage/base', 'PhabricatorPHIDLookupController' => 'applications/phid/controller/lookup', 'PhabricatorPaste' => 'applications/paste/storage/paste', 'PhabricatorPasteController' => 'applications/paste/controller/base', 'PhabricatorPasteDAO' => 'applications/paste/storage/base', 'PhabricatorPasteListController' => 'applications/paste/controller/list', 'PhabricatorPasteViewController' => 'applications/paste/controller/view', 'PhabricatorPeopleController' => 'applications/people/controller/base', 'PhabricatorPeopleEditController' => 'applications/people/controller/edit', 'PhabricatorPeopleListController' => 'applications/people/controller/list', 'PhabricatorPeopleLogsController' => 'applications/people/controller/logs', 'PhabricatorPeopleProfileController' => 'applications/people/controller/profile', 'PhabricatorProfileHeaderView' => 'view/layout/profileheader', 'PhabricatorProject' => 'applications/project/storage/project', 'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation', 'PhabricatorProjectConstants' => 'applications/project/constants/base', 'PhabricatorProjectController' => 'applications/project/controller/base', 'PhabricatorProjectCreateController' => 'applications/project/controller/create', 'PhabricatorProjectDAO' => 'applications/project/storage/base', 'PhabricatorProjectEditor' => 'applications/project/editor/project', 'PhabricatorProjectListController' => 'applications/project/controller/list', 'PhabricatorProjectNameCollisionException' => 'applications/project/exception/namecollison', 'PhabricatorProjectProfile' => 'applications/project/storage/profile', 'PhabricatorProjectProfileController' => 'applications/project/controller/profile', 'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit', 'PhabricatorProjectQuery' => 'applications/project/query/project', 'PhabricatorProjectQueryUtil' => 'applications/project/query/util', 'PhabricatorProjectStatus' => 'applications/project/constants/status', 'PhabricatorProjectSubproject' => 'applications/project/storage/subproject', 'PhabricatorProjectTransaction' => 'applications/project/storage/transaction', 'PhabricatorProjectTransactionType' => 'applications/project/constants/transaction', 'PhabricatorProjectUpdateController' => 'applications/project/controller/update', 'PhabricatorRedirectController' => 'applications/base/controller/redirect', 'PhabricatorRefreshCSRFController' => 'applications/auth/controller/refresh', 'PhabricatorRemarkupRuleDifferential' => 'infrastructure/markup/remarkup/markuprule/differential', 'PhabricatorRemarkupRuleDifferentialHandle' => 'infrastructure/markup/remarkup/markuprule/handle/differential', 'PhabricatorRemarkupRuleDiffusion' => 'infrastructure/markup/remarkup/markuprule/diffusion', 'PhabricatorRemarkupRuleEmbedFile' => 'infrastructure/markup/remarkup/markuprule/embedobject', 'PhabricatorRemarkupRuleImageMacro' => 'infrastructure/markup/remarkup/markuprule/imagemacro', 'PhabricatorRemarkupRuleManiphest' => 'infrastructure/markup/remarkup/markuprule/maniphest', 'PhabricatorRemarkupRuleManiphestHandle' => 'infrastructure/markup/remarkup/markuprule/handle/maniphest', 'PhabricatorRemarkupRuleMention' => 'infrastructure/markup/remarkup/markuprule/mention', 'PhabricatorRemarkupRuleObjectHandle' => 'infrastructure/markup/remarkup/markuprule/handle', 'PhabricatorRemarkupRuleObjectName' => 'infrastructure/markup/remarkup/markuprule/objectname', 'PhabricatorRemarkupRulePaste' => 'infrastructure/markup/remarkup/markuprule/paste', 'PhabricatorRemarkupRulePhriction' => 'infrastructure/markup/remarkup/markuprule/phriction', 'PhabricatorRemarkupRuleProxyImage' => 'infrastructure/markup/remarkup/markuprule/proxyimage', 'PhabricatorRemarkupRuleYoutube' => 'infrastructure/markup/remarkup/markuprule/youtube', 'PhabricatorRepository' => 'applications/repository/storage/repository', 'PhabricatorRepositoryArcanistProject' => 'applications/repository/storage/arcanistproject', 'PhabricatorRepositoryArcanistProjectEditController' => 'applications/repository/controller/arcansistprojectedit', 'PhabricatorRepositoryCommit' => 'applications/repository/storage/commit', 'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/base', 'PhabricatorRepositoryCommitData' => 'applications/repository/storage/commitdata', 'PhabricatorRepositoryCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/base', 'PhabricatorRepositoryCommitHeraldWorker' => 'applications/repository/worker/herald', 'PhabricatorRepositoryCommitMessageDetailParser' => 'applications/repository/parser/base', 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/base', 'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/owner', 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/base', 'PhabricatorRepositoryCommitTaskDaemon' => 'applications/repository/daemon/committask', 'PhabricatorRepositoryController' => 'applications/repository/controller/base', 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/create', 'PhabricatorRepositoryDAO' => 'applications/repository/storage/base', 'PhabricatorRepositoryDaemon' => 'applications/repository/daemon/base', 'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'applications/repository/parser/default', 'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/delete', 'PhabricatorRepositoryEditController' => 'applications/repository/controller/edit', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/git', 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/git', 'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'applications/repository/daemon/commitdiscovery/git/__tests__', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/git', 'PhabricatorRepositoryGitFetchDaemon' => 'applications/repository/daemon/gitfetch', 'PhabricatorRepositoryListController' => 'applications/repository/controller/list', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/mercurial', 'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/mercurial', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/mercurial', 'PhabricatorRepositoryMercurialPullDaemon' => 'applications/repository/daemon/mercurialpull', 'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/pulllocal', 'PhabricatorRepositoryShortcut' => 'applications/repository/storage/shortcut', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/svn', 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'applications/repository/daemon/commitdiscovery/svn', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/svn', 'PhabricatorRepositorySymbol' => 'applications/repository/storage/symbol', 'PhabricatorRepositoryTestCase' => 'applications/repository/storage/repository/__tests__', 'PhabricatorRepositoryType' => 'applications/repository/constants/repositorytype', 'PhabricatorS3FileStorageEngine' => 'applications/files/engine/s3', 'PhabricatorSQLPatchList' => 'infrastructure/setup/sql', 'PhabricatorSearchAbstractDocument' => 'applications/search/index/abstractdocument', 'PhabricatorSearchAttachController' => 'applications/search/controller/attach', 'PhabricatorSearchBaseController' => 'applications/search/controller/base', 'PhabricatorSearchCommitIndexer' => 'applications/search/index/indexer/repository', 'PhabricatorSearchController' => 'applications/search/controller/search', 'PhabricatorSearchDAO' => 'applications/search/storage/base', 'PhabricatorSearchDifferentialIndexer' => 'applications/search/index/indexer/differential', 'PhabricatorSearchDocument' => 'applications/search/storage/document/document', 'PhabricatorSearchDocumentField' => 'applications/search/storage/document/field', 'PhabricatorSearchDocumentIndexer' => 'applications/search/index/indexer/base', 'PhabricatorSearchDocumentRelationship' => 'applications/search/storage/document/relationship', 'PhabricatorSearchEngine' => 'applications/search/engine/base', 'PhabricatorSearchEngineMySQL' => 'applications/search/engine/mysql', 'PhabricatorSearchEngineSelector' => 'applications/search/selector/base', 'PhabricatorSearchField' => 'applications/search/constants/field', 'PhabricatorSearchIndexController' => 'applications/search/controller/index', 'PhabricatorSearchManiphestIndexer' => 'applications/search/index/indexer/maniphest', 'PhabricatorSearchPhrictionIndexer' => 'applications/search/index/indexer/phriction', 'PhabricatorSearchQuery' => 'applications/search/storage/query', 'PhabricatorSearchRelationship' => 'applications/search/constants/relationship', 'PhabricatorSearchResultView' => 'applications/search/view/searchresult', 'PhabricatorSearchScope' => 'applications/search/constants/scope', 'PhabricatorSearchSelectController' => 'applications/search/controller/select', 'PhabricatorSearchUserIndexer' => 'applications/search/index/indexer/user', 'PhabricatorSetup' => 'infrastructure/setup', 'PhabricatorSlowvoteChoice' => 'applications/slowvote/storage/choice', 'PhabricatorSlowvoteComment' => 'applications/slowvote/storage/comment', 'PhabricatorSlowvoteController' => 'applications/slowvote/controller/base', 'PhabricatorSlowvoteCreateController' => 'applications/slowvote/controller/create', 'PhabricatorSlowvoteDAO' => 'applications/slowvote/storage/base', 'PhabricatorSlowvoteListController' => 'applications/slowvote/controller/list', 'PhabricatorSlowvoteOption' => 'applications/slowvote/storage/option', 'PhabricatorSlowvotePoll' => 'applications/slowvote/storage/poll', 'PhabricatorSlowvotePollController' => 'applications/slowvote/controller/poll', 'PhabricatorStandardPageView' => 'view/page/standard', 'PhabricatorStatusController' => 'applications/status/base', 'PhabricatorSymbolNameLinter' => 'infrastructure/lint/hook/xhpastsymbolname', 'PhabricatorSyntaxHighlighter' => 'applications/markup/syntax', 'PhabricatorTaskmasterDaemon' => 'infrastructure/daemon/workers/taskmaster', 'PhabricatorTestCase' => 'infrastructure/testing/testcase', 'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/cursor', 'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/base', 'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/event', 'PhabricatorTimelineEventData' => 'infrastructure/daemon/timeline/storage/eventdata', 'PhabricatorTimelineIterator' => 'infrastructure/daemon/timeline/cursor/iterator', 'PhabricatorTimer' => 'applications/countdown/storage/timer', 'PhabricatorTransactionView' => 'view/layout/transaction', 'PhabricatorTransformedFile' => 'applications/files/storage/transformed', 'PhabricatorTrivialTestCase' => 'infrastructure/testing/testcase/__tests__', 'PhabricatorTypeaheadCommonDatasourceController' => 'applications/typeahead/controller/common', 'PhabricatorTypeaheadDatasourceController' => 'applications/typeahead/controller/base', 'PhabricatorUIExample' => 'applications/uiexample/examples/base', 'PhabricatorUIExampleController' => 'applications/uiexample/controller/base', 'PhabricatorUIExampleRenderController' => 'applications/uiexample/controller/render', 'PhabricatorUIListFilterExample' => 'applications/uiexample/examples/listfilter', 'PhabricatorUIPagerExample' => 'applications/uiexample/examples/pager', 'PhabricatorUser' => 'applications/people/storage/user', 'PhabricatorUserAccountSettingsPanelController' => 'applications/people/controller/settings/panels/account', 'PhabricatorUserConduitSettingsPanelController' => 'applications/people/controller/settings/panels/conduit', 'PhabricatorUserDAO' => 'applications/people/storage/base', 'PhabricatorUserEmailPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/emailpref', 'PhabricatorUserEmailSettingsPanelController' => 'applications/people/controller/settings/panels/email', 'PhabricatorUserLog' => 'applications/people/storage/log', 'PhabricatorUserOAuthInfo' => 'applications/people/storage/useroauthinfo', 'PhabricatorUserOAuthSettingsPanelController' => 'applications/people/controller/settings/panels/oauth', 'PhabricatorUserPasswordSettingsPanelController' => 'applications/people/controller/settings/panels/password', 'PhabricatorUserPreferenceSettingsPanelController' => 'applications/people/controller/settings/panels/preferences', 'PhabricatorUserPreferences' => 'applications/people/storage/preferences', 'PhabricatorUserProfile' => 'applications/people/storage/profile', 'PhabricatorUserProfileSettingsPanelController' => 'applications/people/controller/settings/panels/profile', 'PhabricatorUserSSHKey' => 'applications/people/storage/usersshkey', 'PhabricatorUserSSHKeysSettingsPanelController' => 'applications/people/controller/settings/panels/sshkeys', 'PhabricatorUserSettingsController' => 'applications/people/controller/settings', 'PhabricatorUserSettingsPanelController' => 'applications/people/controller/settings/panels/base', 'PhabricatorUserTestCase' => 'applications/people/storage/user/__tests__', 'PhabricatorWorker' => 'infrastructure/daemon/workers/worker', 'PhabricatorWorkerDAO' => 'infrastructure/daemon/workers/storage/base', 'PhabricatorWorkerTask' => 'infrastructure/daemon/workers/storage/task', 'PhabricatorWorkerTaskData' => 'infrastructure/daemon/workers/storage/taskdata', 'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/workertaskdetail', 'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/workertaskupdate', 'PhabricatorXHPASTViewController' => 'applications/xhpastview/controller/base', 'PhabricatorXHPASTViewDAO' => 'applications/xhpastview/storage/base', 'PhabricatorXHPASTViewFrameController' => 'applications/xhpastview/controller/viewframe', 'PhabricatorXHPASTViewFramesetController' => 'applications/xhpastview/controller/viewframeset', 'PhabricatorXHPASTViewInputController' => 'applications/xhpastview/controller/viewinput', 'PhabricatorXHPASTViewPanelController' => 'applications/xhpastview/controller/viewpanel', 'PhabricatorXHPASTViewParseTree' => 'applications/xhpastview/storage/parsetree', 'PhabricatorXHPASTViewRunController' => 'applications/xhpastview/controller/run', 'PhabricatorXHPASTViewStreamController' => 'applications/xhpastview/controller/viewstream', 'PhabricatorXHPASTViewTreeController' => 'applications/xhpastview/controller/viewtree', 'PhabricatorXHProfController' => 'applications/xhprof/controller/base', 'PhabricatorXHProfProfileController' => 'applications/xhprof/controller/profile', 'PhabricatorXHProfProfileSymbolView' => 'applications/xhprof/view/symbol', 'PhabricatorXHProfProfileTopLevelView' => 'applications/xhprof/view/toplevel', 'PhabricatorXHProfProfileView' => 'applications/xhprof/view/base', 'PhrictionActionConstants' => 'applications/phriction/constants/action', 'PhrictionChangeType' => 'applications/phriction/constants/changetype', 'PhrictionConstants' => 'applications/phriction/constants/base', 'PhrictionContent' => 'applications/phriction/storage/content', 'PhrictionController' => 'applications/phriction/controller/base', 'PhrictionDAO' => 'applications/phriction/storage/base', 'PhrictionDeleteController' => 'applications/phriction/controller/delete', 'PhrictionDiffController' => 'applications/phriction/controller/diff', 'PhrictionDocument' => 'applications/phriction/storage/document', 'PhrictionDocumentController' => 'applications/phriction/controller/document', 'PhrictionDocumentEditor' => 'applications/phriction/editor/document', 'PhrictionDocumentPreviewController' => 'applications/phriction/controller/documentpreview', 'PhrictionDocumentStatus' => 'applications/phriction/constants/documentstatus', 'PhrictionDocumentTestCase' => 'applications/phriction/storage/document/__tests__', 'PhrictionEditController' => 'applications/phriction/controller/edit', 'PhrictionHistoryController' => 'applications/phriction/controller/history', 'PhrictionListController' => 'applications/phriction/controller/list', 'QueryFormattingTestCase' => 'storage/qsprintf/__tests__', ), 'function' => array( '__phabricator_format_local_time' => 'view/utils', '_qsprintf_check_scalar_type' => 'storage/qsprintf', '_qsprintf_check_type' => 'storage/qsprintf', 'celerity_generate_unique_node_id' => 'infrastructure/celerity/api', 'celerity_register_resource_map' => 'infrastructure/celerity/map', 'javelin_render_tag' => 'infrastructure/javelin/markup', 'phabricator_date' => 'view/utils', 'phabricator_datetime' => 'view/utils', 'phabricator_format_relative_time' => 'view/utils', 'phabricator_format_units_generic' => 'view/utils', 'phabricator_render_form' => 'infrastructure/javelin/markup', 'phabricator_time' => 'view/utils', 'qsprintf' => 'storage/qsprintf', 'queryfx' => 'storage/queryfx', 'queryfx_all' => 'storage/queryfx', 'queryfx_one' => 'storage/queryfx', 'require_celerity_resource' => 'infrastructure/celerity/api', 'vqsprintf' => 'storage/qsprintf', 'vqueryfx' => 'storage/queryfx', 'vqueryfx_all' => 'storage/queryfx', 'xsprintf_query' => 'storage/qsprintf', ), 'requires_class' => array( 'Aphront304Response' => 'AphrontResponse', 'Aphront400Response' => 'AphrontResponse', 'Aphront403Response' => 'AphrontWebpageResponse', 'Aphront404Response' => 'AphrontWebpageResponse', 'AphrontAjaxResponse' => 'AphrontResponse', 'AphrontAttachedFileView' => 'AphrontView', 'AphrontCSRFException' => 'AphrontException', 'AphrontCalendarMonthView' => 'AphrontView', 'AphrontContextBarView' => 'AphrontView', 'AphrontCrumbsView' => 'AphrontView', 'AphrontDefaultApplicationConfiguration' => 'AphrontApplicationConfiguration', 'AphrontDefaultApplicationController' => 'AphrontController', 'AphrontDialogResponse' => 'AphrontResponse', 'AphrontDialogView' => 'AphrontView', 'AphrontErrorView' => 'AphrontView', 'AphrontFilePreviewView' => 'AphrontView', 'AphrontFileResponse' => 'AphrontResponse', 'AphrontFormCheckboxControl' => 'AphrontFormControl', 'AphrontFormControl' => 'AphrontView', 'AphrontFormDividerControl' => 'AphrontFormControl', 'AphrontFormDragAndDropUploadControl' => 'AphrontFormControl', 'AphrontFormFileControl' => 'AphrontFormControl', 'AphrontFormLayoutView' => 'AphrontView', 'AphrontFormMarkupControl' => 'AphrontFormControl', 'AphrontFormPasswordControl' => 'AphrontFormControl', 'AphrontFormRadioButtonControl' => 'AphrontFormControl', 'AphrontFormRecaptchaControl' => 'AphrontFormControl', 'AphrontFormSelectControl' => 'AphrontFormControl', 'AphrontFormStaticControl' => 'AphrontFormControl', 'AphrontFormSubmitControl' => 'AphrontFormControl', 'AphrontFormTextAreaControl' => 'AphrontFormControl', 'AphrontFormTextControl' => 'AphrontFormControl', 'AphrontFormToggleButtonsControl' => 'AphrontFormControl', 'AphrontFormTokenizerControl' => 'AphrontFormControl', 'AphrontFormView' => 'AphrontView', 'AphrontHTTPSinkTestCase' => 'PhabricatorTestCase', 'AphrontHeadsupActionListView' => 'AphrontView', 'AphrontHeadsupActionView' => 'AphrontView', 'AphrontIsolatedDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontIsolatedDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontIsolatedHTTPSink' => 'AphrontHTTPSink', 'AphrontJSONResponse' => 'AphrontResponse', 'AphrontJavelinView' => 'AphrontView', 'AphrontKeyboardShortcutsAvailableView' => 'AphrontView', 'AphrontListFilterView' => 'AphrontView', 'AphrontMiniPanelView' => 'AphrontView', 'AphrontMySQLDatabaseConnection' => 'AphrontDatabaseConnection', 'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', 'AphrontNullView' => 'AphrontView', 'AphrontPHPHTTPSink' => 'AphrontHTTPSink', 'AphrontPageView' => 'AphrontView', 'AphrontPagerView' => 'AphrontView', 'AphrontPanelView' => 'AphrontView', 'AphrontPlainTextResponse' => 'AphrontResponse', 'AphrontQueryAccessDeniedException' => 'AphrontQueryRecoverableException', 'AphrontQueryConnectionException' => 'AphrontQueryException', 'AphrontQueryConnectionLostException' => 'AphrontQueryRecoverableException', 'AphrontQueryCountException' => 'AphrontQueryException', 'AphrontQueryDuplicateKeyException' => 'AphrontQueryException', 'AphrontQueryObjectMissingException' => 'AphrontQueryException', 'AphrontQueryParameterException' => 'AphrontQueryException', 'AphrontQueryRecoverableException' => 'AphrontQueryException', 'AphrontRedirectException' => 'AphrontException', 'AphrontRedirectResponse' => 'AphrontResponse', 'AphrontReloadResponse' => 'AphrontRedirectResponse', 'AphrontRequestFailureView' => 'AphrontView', 'AphrontRequestTestCase' => 'PhabricatorTestCase', 'AphrontSideNavFilterView' => 'AphrontView', 'AphrontSideNavView' => 'AphrontView', 'AphrontTableView' => 'AphrontView', 'AphrontTokenizerTemplateView' => 'AphrontView', 'AphrontTypeaheadTemplateView' => 'AphrontView', 'AphrontWebpageResponse' => 'AphrontResponse', 'CelerityResourceController' => 'AphrontController', 'CelerityResourceGraph' => 'AbstractDirectedGraph', 'ConduitAPI_arcanist_Method' => 'ConduitAPIMethod', 'ConduitAPI_arcanist_projectinfo_Method' => 'ConduitAPI_arcanist_Method', 'ConduitAPI_chatlog_Method' => 'ConduitAPIMethod', 'ConduitAPI_chatlog_query_Method' => 'ConduitAPI_chatlog_Method', 'ConduitAPI_chatlog_record_Method' => 'ConduitAPI_chatlog_Method', 'ConduitAPI_conduit_connect_Method' => 'ConduitAPIMethod', 'ConduitAPI_conduit_getcertificate_Method' => 'ConduitAPIMethod', 'ConduitAPI_conduit_ping_Method' => 'ConduitAPIMethod', 'ConduitAPI_daemon_launched_Method' => 'ConduitAPIMethod', 'ConduitAPI_daemon_log_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_createcomment_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_creatediff_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_createrevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_find_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getalldiffs_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getcommitmessage_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getcommitpaths_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getdiff_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getrevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getrevisioncomments_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_getrevisionfeedback_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_markcommitted_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_parsecommitmessage_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_setdiffproperty_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updaterevision_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updatetaskrevisionassoc_Method' => 'ConduitAPIMethod', 'ConduitAPI_differential_updateunitresults_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_findsymbols_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_getcommits_Method' => 'ConduitAPIMethod', 'ConduitAPI_diffusion_getrecentcommitsbypath_Method' => 'ConduitAPIMethod', 'ConduitAPI_feed_publish_Method' => 'ConduitAPIMethod', 'ConduitAPI_feed_query_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_download_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_info_Method' => 'ConduitAPIMethod', 'ConduitAPI_file_upload_Method' => 'ConduitAPIMethod', 'ConduitAPI_maniphest_Method' => 'ConduitAPIMethod', 'ConduitAPI_maniphest_createtask_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_find_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_gettasktransactions_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_info_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_maniphest_update_Method' => 'ConduitAPI_maniphest_Method', 'ConduitAPI_paste_Method' => 'ConduitAPIMethod', 'ConduitAPI_paste_create_Method' => 'ConduitAPI_paste_Method', 'ConduitAPI_paste_info_Method' => 'ConduitAPI_paste_Method', 'ConduitAPI_path_getowners_Method' => 'ConduitAPIMethod', 'ConduitAPI_phid_Method' => 'ConduitAPIMethod', 'ConduitAPI_phid_info_Method' => 'ConduitAPI_phid_Method', 'ConduitAPI_phid_query_Method' => 'ConduitAPI_phid_Method', 'ConduitAPI_phriction_Method' => 'ConduitAPIMethod', 'ConduitAPI_phriction_edit_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_phriction_history_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_phriction_info_Method' => 'ConduitAPI_phriction_Method', 'ConduitAPI_project_Method' => 'ConduitAPIMethod', 'ConduitAPI_project_query_Method' => 'ConduitAPI_project_Method', 'ConduitAPI_remarkup_process_Method' => 'ConduitAPIMethod', 'ConduitAPI_slowvote_info_Method' => 'ConduitAPIMethod', 'ConduitAPI_user_Method' => 'ConduitAPIMethod', 'ConduitAPI_user_find_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_info_Method' => 'ConduitAPI_user_Method', 'ConduitAPI_user_whoami_Method' => 'ConduitAPI_user_Method', 'DarkConsoleConfigPlugin' => 'DarkConsolePlugin', 'DarkConsoleController' => 'PhabricatorController', 'DarkConsoleErrorLogPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPlugin' => 'DarkConsolePlugin', 'DarkConsoleEventPluginAPI' => 'PhutilEventListener', 'DarkConsoleRequestPlugin' => 'DarkConsolePlugin', 'DarkConsoleServicesPlugin' => 'DarkConsolePlugin', 'DarkConsoleXHProfPlugin' => 'DarkConsolePlugin', 'DifferentialActionHasNoEffectException' => 'DifferentialException', 'DifferentialAddCommentView' => 'AphrontView', 'DifferentialAffectedPath' => 'DifferentialDAO', 'DifferentialApplyPatchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialArcanistProjectFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuthorFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialAuxiliaryField' => 'DifferentialDAO', 'DifferentialBlameRevisionFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialBranchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialCCWelcomeMail' => 'DifferentialReviewRequestMail', 'DifferentialCCsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialChangeset' => 'DifferentialDAO', 'DifferentialChangesetDetailView' => 'AphrontView', 'DifferentialChangesetListView' => 'AphrontView', 'DifferentialChangesetViewController' => 'DifferentialController', 'DifferentialComment' => 'DifferentialDAO', 'DifferentialCommentMail' => 'DifferentialMail', 'DifferentialCommentPreviewController' => 'DifferentialController', 'DifferentialCommentSaveController' => 'DifferentialController', 'DifferentialCommitsFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialController' => 'PhabricatorController', 'DifferentialDAO' => 'PhabricatorLiskDAO', 'DifferentialDateCreatedFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDateModifiedFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDefaultFieldSelector' => 'DifferentialFieldSelector', 'DifferentialDependenciesFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialDiff' => 'DifferentialDAO', 'DifferentialDiffContentMail' => 'DifferentialMail', 'DifferentialDiffCreateController' => 'DifferentialController', 'DifferentialDiffProperty' => 'DifferentialDAO', 'DifferentialDiffTableOfContentsView' => 'AphrontView', 'DifferentialDiffViewController' => 'DifferentialController', 'DifferentialExceptionMail' => 'DifferentialMail', 'DifferentialExportPatchFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialGitSVNIDFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialHostFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialHunk' => 'DifferentialDAO', 'DifferentialInlineComment' => 'DifferentialDAO', 'DifferentialInlineCommentEditController' => 'DifferentialController', 'DifferentialInlineCommentPreviewController' => 'DifferentialController', 'DifferentialInlineCommentView' => 'AphrontView', 'DifferentialLinesFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialLintFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialLocalCommitsView' => 'AphrontView', 'DifferentialManiphestTasksFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialNewDiffMail' => 'DifferentialReviewRequestMail', 'DifferentialPathFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialPrimaryPaneView' => 'AphrontView', 'DifferentialReplyHandler' => 'PhabricatorMailReplyHandler', 'DifferentialRevertPlanFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialReviewRequestMail' => 'DifferentialMail', 'DifferentialReviewedByFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialReviewersFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevision' => 'DifferentialDAO', 'DifferentialRevisionCommentListView' => 'AphrontView', 'DifferentialRevisionCommentView' => 'AphrontView', 'DifferentialRevisionDetailView' => 'AphrontView', 'DifferentialRevisionEditController' => 'DifferentialController', 'DifferentialRevisionIDFieldParserTestCase' => 'PhabricatorTestCase', 'DifferentialRevisionIDFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevisionListController' => 'DifferentialController', 'DifferentialRevisionListView' => 'AphrontView', 'DifferentialRevisionStatsController' => 'DifferentialController', 'DifferentialRevisionStatsView' => 'AphrontView', 'DifferentialRevisionStatusFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialRevisionUpdateHistoryView' => 'AphrontView', 'DifferentialRevisionViewController' => 'DifferentialController', 'DifferentialSubscribeController' => 'DifferentialController', 'DifferentialSummaryFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialTestPlanFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialTitleFieldSpecification' => 'DifferentialFieldSpecification', 'DifferentialUnitFieldSpecification' => 'DifferentialFieldSpecification', 'DiffusionBranchTableView' => 'DiffusionView', 'DiffusionBrowseController' => 'DiffusionController', 'DiffusionBrowseFileController' => 'DiffusionController', 'DiffusionBrowseTableView' => 'DiffusionView', 'DiffusionChangeController' => 'DiffusionController', 'DiffusionCommentListView' => 'AphrontView', 'DiffusionCommentView' => 'AphrontView', 'DiffusionCommitChangeTableView' => 'DiffusionView', 'DiffusionCommitController' => 'DiffusionController', 'DiffusionCommitListController' => 'DiffusionController', 'DiffusionContainsQuery' => 'DiffusionQuery', 'DiffusionController' => 'PhabricatorController', 'DiffusionDiffController' => 'DiffusionController', 'DiffusionEmptyResultView' => 'DiffusionView', 'DiffusionGitBranchQuery' => 'DiffusionBranchQuery', 'DiffusionGitBranchQueryTestCase' => 'PhabricatorTestCase', 'DiffusionGitBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionGitContainsQuery' => 'DiffusionContainsQuery', 'DiffusionGitDiffQuery' => 'DiffusionDiffQuery', 'DiffusionGitFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionGitHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionGitLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionGitRequest' => 'DiffusionRequest', 'DiffusionHistoryController' => 'DiffusionController', 'DiffusionHistoryTableView' => 'DiffusionView', 'DiffusionHomeController' => 'DiffusionController', 'DiffusionLastModifiedController' => 'DiffusionController', 'DiffusionMercurialBranchQuery' => 'DiffusionBranchQuery', 'DiffusionMercurialBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionMercurialContainsQuery' => 'DiffusionContainsQuery', 'DiffusionMercurialDiffQuery' => 'DiffusionDiffQuery', 'DiffusionMercurialFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionMercurialHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionMercurialLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionMercurialRequest' => 'DiffusionRequest', 'DiffusionPathCompleteController' => 'DiffusionController', 'DiffusionPathQueryTestCase' => 'PhabricatorTestCase', 'DiffusionPathValidateController' => 'DiffusionController', 'DiffusionRepositoryController' => 'DiffusionController', 'DiffusionSVNContainsQuery' => 'DiffusionContainsQuery', 'DiffusionSvnBrowseQuery' => 'DiffusionBrowseQuery', 'DiffusionSvnDiffQuery' => 'DiffusionDiffQuery', 'DiffusionSvnFileContentQuery' => 'DiffusionFileContentQuery', 'DiffusionSvnHistoryQuery' => 'DiffusionHistoryQuery', 'DiffusionSvnLastModifiedQuery' => 'DiffusionLastModifiedQuery', 'DiffusionSvnRequest' => 'DiffusionRequest', 'DiffusionSymbolController' => 'DiffusionController', 'DiffusionView' => 'AphrontView', 'DrydockAllocatorWorker' => 'PhabricatorWorker', 'DrydockCommandInterface' => 'DrydockInterface', 'DrydockController' => 'PhabricatorController', 'DrydockDAO' => 'PhabricatorLiskDAO', 'DrydockEC2HostBlueprint' => 'DrydockRemoteHostBlueprint', 'DrydockLease' => 'DrydockDAO', 'DrydockLeaseListController' => 'DrydockController', 'DrydockLeaseStatus' => 'DrydockConstants', 'DrydockLocalCommandInterface' => 'DrydockCommandInterface', 'DrydockLocalHostBlueprint' => 'DrydockBlueprint', 'DrydockRemoteHostBlueprint' => 'DrydockBlueprint', 'DrydockResource' => 'DrydockDAO', 'DrydockResourceAllocateController' => 'DrydockController', 'DrydockResourceListController' => 'DrydockController', 'DrydockResourceStatus' => 'DrydockConstants', 'DrydockSSHCommandInterface' => 'DrydockCommandInterface', 'HeraldAction' => 'HeraldDAO', 'HeraldAllRulesController' => 'HeraldController', 'HeraldApplyTranscript' => 'HeraldDAO', 'HeraldCommitAdapter' => 'HeraldObjectAdapter', 'HeraldCondition' => 'HeraldDAO', 'HeraldController' => 'PhabricatorController', 'HeraldDAO' => 'PhabricatorLiskDAO', 'HeraldDeleteController' => 'HeraldController', 'HeraldDifferentialRevisionAdapter' => 'HeraldObjectAdapter', 'HeraldDryRunAdapter' => 'HeraldObjectAdapter', 'HeraldHomeController' => 'HeraldController', 'HeraldNewController' => 'HeraldController', 'HeraldRule' => 'HeraldDAO', 'HeraldRuleController' => 'HeraldController', 'HeraldRuleEdit' => 'HeraldDAO', 'HeraldRuleEditHistoryController' => 'HeraldController', 'HeraldRuleEditHistoryView' => 'AphrontView', 'HeraldRuleListView' => 'AphrontView', 'HeraldTestConsoleController' => 'HeraldController', 'HeraldTranscript' => 'HeraldDAO', 'HeraldTranscriptController' => 'HeraldController', 'HeraldTranscriptListController' => 'HeraldController', 'JavelinReactorExample' => 'PhabricatorUIExample', 'JavelinViewExample' => 'PhabricatorUIExample', 'JavelinViewExampleServerView' => 'AphrontView', 'LiskIsolationTestCase' => 'PhabricatorTestCase', 'LiskIsolationTestDAO' => 'LiskDAO', 'ManiphestAction' => 'PhrictionConstants', 'ManiphestAuxiliaryFieldDefaultSpecification' => 'ManiphestAuxiliaryFieldSpecification', 'ManiphestBatchEditController' => 'ManiphestController', 'ManiphestController' => 'PhabricatorController', 'ManiphestDAO' => 'PhabricatorLiskDAO', 'ManiphestDefaultTaskExtensions' => 'ManiphestTaskExtensions', 'ManiphestReplyHandler' => 'PhabricatorMailReplyHandler', 'ManiphestReportController' => 'ManiphestController', 'ManiphestTask' => 'ManiphestDAO', 'ManiphestTaskAuxiliaryStorage' => 'ManiphestDAO', 'ManiphestTaskDescriptionChangeController' => 'ManiphestController', 'ManiphestTaskDescriptionDiffController' => 'ManiphestTaskDescriptionChangeController', 'ManiphestTaskDescriptionPreviewController' => 'ManiphestController', 'ManiphestTaskDetailController' => 'ManiphestController', 'ManiphestTaskEditController' => 'ManiphestController', 'ManiphestTaskListController' => 'ManiphestController', 'ManiphestTaskListView' => 'ManiphestView', 'ManiphestTaskOwner' => 'ManiphestConstants', 'ManiphestTaskPriority' => 'ManiphestConstants', 'ManiphestTaskProject' => 'ManiphestDAO', 'ManiphestTaskStatus' => 'ManiphestConstants', 'ManiphestTaskSubscriber' => 'ManiphestDAO', 'ManiphestTaskSummaryView' => 'ManiphestView', 'ManiphestTransaction' => 'ManiphestDAO', 'ManiphestTransactionDetailView' => 'ManiphestView', 'ManiphestTransactionListView' => 'ManiphestView', 'ManiphestTransactionPreviewController' => 'ManiphestController', 'ManiphestTransactionSaveController' => 'ManiphestController', 'ManiphestTransactionType' => 'ManiphestConstants', 'ManiphestView' => 'AphrontView', 'MetaMTANotificationType' => 'MetaMTAConstants', 'Phabricator404Controller' => 'PhabricatorController', 'PhabricatorAuditAddCommentController' => 'PhabricatorAuditController', 'PhabricatorAuditComment' => 'PhabricatorAuditDAO', 'PhabricatorAuditController' => 'PhabricatorController', 'PhabricatorAuditDAO' => 'PhabricatorLiskDAO', 'PhabricatorAuditEditController' => 'PhabricatorAuditController', 'PhabricatorAuditListController' => 'PhabricatorAuditController', 'PhabricatorAuditListView' => 'AphrontView', + 'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler', 'PhabricatorAuthController' => 'PhabricatorController', 'PhabricatorCalendarBrowseController' => 'PhabricatorCalendarController', 'PhabricatorCalendarController' => 'PhabricatorController', 'PhabricatorChatLogChannelListController' => 'PhabricatorChatLogController', 'PhabricatorChatLogChannelLogController' => 'PhabricatorChatLogController', 'PhabricatorChatLogController' => 'PhabricatorController', 'PhabricatorChatLogDAO' => 'PhabricatorLiskDAO', 'PhabricatorChatLogEvent' => 'PhabricatorChatLogDAO', 'PhabricatorChatLogEventType' => 'PhabricatorChatLogConstants', 'PhabricatorConduitAPIController' => 'PhabricatorConduitController', 'PhabricatorConduitCertificateToken' => 'PhabricatorConduitDAO', 'PhabricatorConduitConnectionLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitConsoleController' => 'PhabricatorConduitController', 'PhabricatorConduitController' => 'PhabricatorController', 'PhabricatorConduitDAO' => 'PhabricatorLiskDAO', 'PhabricatorConduitLogController' => 'PhabricatorConduitController', 'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO', 'PhabricatorConduitTokenController' => 'PhabricatorConduitController', 'PhabricatorContentSourceView' => 'AphrontView', 'PhabricatorController' => 'AphrontController', 'PhabricatorCountdownController' => 'PhabricatorController', 'PhabricatorCountdownDAO' => 'PhabricatorLiskDAO', 'PhabricatorCountdownDeleteController' => 'PhabricatorCountdownController', 'PhabricatorCountdownEditController' => 'PhabricatorCountdownController', 'PhabricatorCountdownListController' => 'PhabricatorCountdownController', 'PhabricatorCountdownViewController' => 'PhabricatorCountdownController', 'PhabricatorDaemon' => 'PhutilDaemon', 'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController', 'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonController' => 'PhabricatorController', 'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO', 'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO', 'PhabricatorDaemonLogEventsView' => 'AphrontView', 'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController', 'PhabricatorDaemonLogListView' => 'AphrontView', 'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController', 'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController', 'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController', 'PhabricatorDefaultFileStorageEngineSelector' => 'PhabricatorFileStorageEngineSelector', 'PhabricatorDefaultSearchEngineSelector' => 'PhabricatorSearchEngineSelector', 'PhabricatorDirectoryCategory' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryCategoryDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryCategoryViewController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryController' => 'PhabricatorController', 'PhabricatorDirectoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorDirectoryEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItem' => 'PhabricatorDirectoryDAO', 'PhabricatorDirectoryItemDeleteController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryItemEditController' => 'PhabricatorDirectoryController', 'PhabricatorDirectoryMainController' => 'PhabricatorDirectoryController', 'PhabricatorDisabledUserController' => 'PhabricatorAuthController', 'PhabricatorDraft' => 'PhabricatorDraftDAO', 'PhabricatorDraftDAO' => 'PhabricatorLiskDAO', 'PhabricatorEmailLoginController' => 'PhabricatorAuthController', 'PhabricatorEmailTokenController' => 'PhabricatorAuthController', 'PhabricatorEnvTestCase' => 'PhabricatorTestCase', 'PhabricatorEvent' => 'PhutilEvent', 'PhabricatorEventType' => 'PhutilEventType', 'PhabricatorFeedController' => 'PhabricatorController', 'PhabricatorFeedDAO' => 'PhabricatorLiskDAO', 'PhabricatorFeedPublicStreamController' => 'PhabricatorFeedController', 'PhabricatorFeedStoryAudit' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryData' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryDifferential' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryManiphest' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryPhriction' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryProject' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryReference' => 'PhabricatorFeedDAO', 'PhabricatorFeedStoryStatus' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryTypeConstants' => 'PhabricatorFeedConstants', 'PhabricatorFeedStoryUnknown' => 'PhabricatorFeedStory', 'PhabricatorFeedStoryView' => 'PhabricatorFeedView', 'PhabricatorFeedView' => 'AphrontView', 'PhabricatorFile' => 'PhabricatorFileDAO', 'PhabricatorFileController' => 'PhabricatorController', 'PhabricatorFileDAO' => 'PhabricatorLiskDAO', 'PhabricatorFileDataController' => 'PhabricatorFileController', 'PhabricatorFileDeleteController' => 'PhabricatorFileController', 'PhabricatorFileDropUploadController' => 'PhabricatorFileController', 'PhabricatorFileImageMacro' => 'PhabricatorFileDAO', 'PhabricatorFileInfoController' => 'PhabricatorFileController', 'PhabricatorFileListController' => 'PhabricatorFileController', 'PhabricatorFileMacroDeleteController' => 'PhabricatorFileController', 'PhabricatorFileMacroEditController' => 'PhabricatorFileController', 'PhabricatorFileMacroListController' => 'PhabricatorFileController', 'PhabricatorFileProxyController' => 'PhabricatorFileController', 'PhabricatorFileProxyImage' => 'PhabricatorFileDAO', 'PhabricatorFileSideNavView' => 'AphrontView', 'PhabricatorFileStorageBlob' => 'PhabricatorFileDAO', 'PhabricatorFileTransformController' => 'PhabricatorFileController', 'PhabricatorFileUploadController' => 'PhabricatorFileController', 'PhabricatorFileUploadView' => 'AphrontView', 'PhabricatorGarbageCollectorDaemon' => 'PhabricatorDaemon', 'PhabricatorGoodForNothingWorker' => 'PhabricatorWorker', 'PhabricatorHelpController' => 'PhabricatorController', 'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', 'PhabricatorIRCBot' => 'PhabricatorDaemon', 'PhabricatorIRCDifferentialNotificationHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCLogHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCObjectNameHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCProtocolHandler' => 'PhabricatorIRCHandler', 'PhabricatorIRCWhatsNewHandler' => 'PhabricatorIRCHandler', 'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase', 'PhabricatorJavelinLinter' => 'ArcanistLinter', 'PhabricatorLintEngine' => 'PhutilLintEngine', 'PhabricatorLiskDAO' => 'LiskDAO', 'PhabricatorLocalDiskFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', 'PhabricatorLoginController' => 'PhabricatorAuthController', 'PhabricatorLoginValidateController' => 'PhabricatorAuthController', 'PhabricatorLogoutController' => 'PhabricatorAuthController', 'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter', 'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter', 'PhabricatorMetaMTAController' => 'PhabricatorController', 'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO', 'PhabricatorMetaMTADaemon' => 'PhabricatorDaemon', 'PhabricatorMetaMTAEmailBodyParserTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailTestCase' => 'PhabricatorTestCase', 'PhabricatorMetaMTAMailingList' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTAMailingListEditController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAMailingListsController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedListController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAReceivedMail' => 'PhabricatorMetaMTADAO', 'PhabricatorMetaMTASendController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTASendGridReceiveController' => 'PhabricatorMetaMTAController', 'PhabricatorMetaMTAViewController' => 'PhabricatorMetaMTAController', 'PhabricatorMySQLFileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorOAuthClientAuthorization' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthClientAuthorizationBaseController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthClientAuthorizationDeleteController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientAuthorizationEditController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientAuthorizationListController' => 'PhabricatorOAuthClientAuthorizationBaseController', 'PhabricatorOAuthClientBaseController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthClientDeleteController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientEditController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientListController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthClientViewController' => 'PhabricatorOAuthClientBaseController', 'PhabricatorOAuthDefaultRegistrationController' => 'PhabricatorOAuthRegistrationController', 'PhabricatorOAuthDiagnosticsController' => 'PhabricatorAuthController', 'PhabricatorOAuthFailureView' => 'AphrontView', 'PhabricatorOAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorOAuthProviderFacebook' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderGitHub' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderGoogle' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthProviderPhabricator' => 'PhabricatorOAuthProvider', 'PhabricatorOAuthRegistrationController' => 'PhabricatorAuthController', 'PhabricatorOAuthResponse' => 'AphrontResponse', 'PhabricatorOAuthServerAccessToken' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerAuthController' => 'PhabricatorAuthController', 'PhabricatorOAuthServerAuthorizationCode' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerClient' => 'PhabricatorOAuthServerDAO', 'PhabricatorOAuthServerController' => 'PhabricatorController', 'PhabricatorOAuthServerDAO' => 'PhabricatorLiskDAO', 'PhabricatorOAuthServerTestController' => 'PhabricatorOAuthServerController', 'PhabricatorOAuthServerTokenController' => 'PhabricatorAuthController', 'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorObjectGraph' => 'AbstractDirectedGraph', 'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants', 'PhabricatorOwnerRelatedListController' => 'PhabricatorOwnersController', 'PhabricatorOwnersController' => 'PhabricatorController', 'PhabricatorOwnersDAO' => 'PhabricatorLiskDAO', 'PhabricatorOwnersDeleteController' => 'PhabricatorOwnersController', 'PhabricatorOwnersDetailController' => 'PhabricatorOwnersController', 'PhabricatorOwnersEditController' => 'PhabricatorOwnersController', 'PhabricatorOwnersListController' => 'PhabricatorOwnersController', 'PhabricatorOwnersOwner' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPackage' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPackageCommitRelationship' => 'PhabricatorOwnersDAO', 'PhabricatorOwnersPath' => 'PhabricatorOwnersDAO', 'PhabricatorPHID' => 'PhabricatorPHIDDAO', 'PhabricatorPHIDController' => 'PhabricatorController', 'PhabricatorPHIDDAO' => 'PhabricatorLiskDAO', 'PhabricatorPHIDLookupController' => 'PhabricatorPHIDController', 'PhabricatorPaste' => 'PhabricatorPasteDAO', 'PhabricatorPasteController' => 'PhabricatorController', 'PhabricatorPasteDAO' => 'PhabricatorLiskDAO', 'PhabricatorPasteListController' => 'PhabricatorPasteController', 'PhabricatorPasteViewController' => 'PhabricatorPasteController', 'PhabricatorPeopleController' => 'PhabricatorController', 'PhabricatorPeopleEditController' => 'PhabricatorPeopleController', 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleProfileController' => 'PhabricatorPeopleController', 'PhabricatorProfileHeaderView' => 'AphrontView', 'PhabricatorProject' => 'PhabricatorProjectDAO', 'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO', 'PhabricatorProjectController' => 'PhabricatorController', 'PhabricatorProjectCreateController' => 'PhabricatorProjectController', 'PhabricatorProjectDAO' => 'PhabricatorLiskDAO', 'PhabricatorProjectListController' => 'PhabricatorProjectController', 'PhabricatorProjectProfile' => 'PhabricatorProjectDAO', 'PhabricatorProjectProfileController' => 'PhabricatorProjectController', 'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController', 'PhabricatorProjectSubproject' => 'PhabricatorProjectDAO', 'PhabricatorProjectTransaction' => 'PhabricatorProjectDAO', 'PhabricatorProjectTransactionType' => 'PhabricatorProjectConstants', 'PhabricatorProjectUpdateController' => 'PhabricatorProjectController', 'PhabricatorRedirectController' => 'PhabricatorController', 'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController', 'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleDifferentialHandle' => 'PhabricatorRemarkupRuleObjectHandle', 'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleEmbedFile' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleManiphest' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRuleManiphestHandle' => 'PhabricatorRemarkupRuleObjectHandle', 'PhabricatorRemarkupRuleMention' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleObjectHandle' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleObjectName' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRulePaste' => 'PhabricatorRemarkupRuleObjectName', 'PhabricatorRemarkupRulePhriction' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleProxyImage' => 'PhutilRemarkupRule', 'PhabricatorRemarkupRuleYoutube' => 'PhutilRemarkupRule', 'PhabricatorRepository' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryArcanistProject' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryArcanistProjectEditController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryCommit' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryCommitDiscoveryDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryCommitHeraldWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitMessageParserWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitOwnersWorker' => 'PhabricatorRepositoryCommitParserWorker', 'PhabricatorRepositoryCommitParserWorker' => 'PhabricatorWorker', 'PhabricatorRepositoryCommitTaskDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryController' => 'PhabricatorController', 'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 'PhabricatorRepositoryDaemon' => 'PhabricatorDaemon', 'PhabricatorRepositoryDefaultCommitMessageDetailParser' => 'PhabricatorRepositoryCommitMessageDetailParser', 'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryGitCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', 'PhabricatorRepositoryGitCommitDiscoveryDaemonTestCase' => 'PhabricatorTestCase', 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryGitFetchDaemon' => 'PhabricatorRepositoryPullLocalDaemon', 'PhabricatorRepositoryListController' => 'PhabricatorRepositoryController', 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositoryMercurialCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositoryMercurialPullDaemon' => 'PhabricatorRepositoryPullLocalDaemon', 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorRepositoryDaemon', 'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 'PhabricatorRepositorySvnCommitDiscoveryDaemon' => 'PhabricatorRepositoryCommitDiscoveryDaemon', 'PhabricatorRepositorySvnCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 'PhabricatorRepositorySymbol' => 'PhabricatorRepositoryDAO', 'PhabricatorRepositoryTestCase' => 'PhabricatorTestCase', 'PhabricatorS3FileStorageEngine' => 'PhabricatorFileStorageEngine', 'PhabricatorSearchAttachController' => 'PhabricatorSearchController', 'PhabricatorSearchBaseController' => 'PhabricatorController', 'PhabricatorSearchCommitIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorSearchController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchDAO' => 'PhabricatorLiskDAO', 'PhabricatorSearchDifferentialIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorSearchDocument' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentField' => 'PhabricatorSearchDAO', 'PhabricatorSearchDocumentRelationship' => 'PhabricatorSearchDAO', 'PhabricatorSearchEngineMySQL' => 'PhabricatorSearchEngine', 'PhabricatorSearchIndexController' => 'PhabricatorSearchBaseController', 'PhabricatorSearchManiphestIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorSearchPhrictionIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorSearchQuery' => 'PhabricatorSearchDAO', 'PhabricatorSearchResultView' => 'AphrontView', 'PhabricatorSearchSelectController' => 'PhabricatorSearchController', 'PhabricatorSearchUserIndexer' => 'PhabricatorSearchDocumentIndexer', 'PhabricatorSlowvoteChoice' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteComment' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvoteController' => 'PhabricatorController', 'PhabricatorSlowvoteCreateController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteDAO' => 'PhabricatorLiskDAO', 'PhabricatorSlowvoteListController' => 'PhabricatorSlowvoteController', 'PhabricatorSlowvoteOption' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePoll' => 'PhabricatorSlowvoteDAO', 'PhabricatorSlowvotePollController' => 'PhabricatorSlowvoteController', 'PhabricatorStandardPageView' => 'AphrontPageView', 'PhabricatorStatusController' => 'PhabricatorController', 'PhabricatorSymbolNameLinter' => 'ArcanistXHPASTLintNamingHook', 'PhabricatorTaskmasterDaemon' => 'PhabricatorDaemon', 'PhabricatorTestCase' => 'ArcanistPhutilTestCase', 'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO', 'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO', 'PhabricatorTimelineEventData' => 'PhabricatorTimelineDAO', 'PhabricatorTimer' => 'PhabricatorCountdownDAO', 'PhabricatorTransactionView' => 'AphrontView', 'PhabricatorTransformedFile' => 'PhabricatorFileDAO', 'PhabricatorTrivialTestCase' => 'PhabricatorTestCase', 'PhabricatorTypeaheadCommonDatasourceController' => 'PhabricatorTypeaheadDatasourceController', 'PhabricatorTypeaheadDatasourceController' => 'PhabricatorController', 'PhabricatorUIExampleController' => 'PhabricatorController', 'PhabricatorUIExampleRenderController' => 'PhabricatorUIExampleController', 'PhabricatorUIListFilterExample' => 'PhabricatorUIExample', 'PhabricatorUIPagerExample' => 'PhabricatorUIExample', 'PhabricatorUser' => 'PhabricatorUserDAO', 'PhabricatorUserAccountSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserConduitSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserDAO' => 'PhabricatorLiskDAO', 'PhabricatorUserEmailPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserEmailSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserLog' => 'PhabricatorUserDAO', 'PhabricatorUserOAuthInfo' => 'PhabricatorUserDAO', 'PhabricatorUserOAuthSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserPasswordSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserPreferenceSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserPreferences' => 'PhabricatorUserDAO', 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 'PhabricatorUserProfileSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserSSHKey' => 'PhabricatorUserDAO', 'PhabricatorUserSSHKeysSettingsPanelController' => 'PhabricatorUserSettingsPanelController', 'PhabricatorUserSettingsController' => 'PhabricatorPeopleController', 'PhabricatorUserSettingsPanelController' => 'PhabricatorPeopleController', 'PhabricatorUserTestCase' => 'PhabricatorTestCase', 'PhabricatorWorkerDAO' => 'PhabricatorLiskDAO', 'PhabricatorWorkerTask' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskData' => 'PhabricatorWorkerDAO', 'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController', 'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController', 'PhabricatorXHPASTViewController' => 'PhabricatorController', 'PhabricatorXHPASTViewDAO' => 'PhabricatorLiskDAO', 'PhabricatorXHPASTViewFrameController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewFramesetController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewInputController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewPanelController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewParseTree' => 'PhabricatorXHPASTViewDAO', 'PhabricatorXHPASTViewRunController' => 'PhabricatorXHPASTViewController', 'PhabricatorXHPASTViewStreamController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHPASTViewTreeController' => 'PhabricatorXHPASTViewPanelController', 'PhabricatorXHProfController' => 'PhabricatorController', 'PhabricatorXHProfProfileController' => 'PhabricatorXHProfController', 'PhabricatorXHProfProfileSymbolView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileTopLevelView' => 'PhabricatorXHProfProfileView', 'PhabricatorXHProfProfileView' => 'AphrontView', 'PhrictionActionConstants' => 'PhrictionConstants', 'PhrictionChangeType' => 'PhrictionConstants', 'PhrictionContent' => 'PhrictionDAO', 'PhrictionController' => 'PhabricatorController', 'PhrictionDAO' => 'PhabricatorLiskDAO', 'PhrictionDeleteController' => 'PhrictionController', 'PhrictionDiffController' => 'PhrictionController', 'PhrictionDocument' => 'PhrictionDAO', 'PhrictionDocumentController' => 'PhrictionController', 'PhrictionDocumentPreviewController' => 'PhrictionController', 'PhrictionDocumentStatus' => 'PhrictionConstants', 'PhrictionDocumentTestCase' => 'PhabricatorTestCase', 'PhrictionEditController' => 'PhrictionController', 'PhrictionHistoryController' => 'PhrictionController', 'PhrictionListController' => 'PhrictionController', 'QueryFormattingTestCase' => 'PhabricatorTestCase', ), 'requires_interface' => array( ), )); diff --git a/src/applications/audit/editor/comment/PhabricatorAuditCommentEditor.php b/src/applications/audit/editor/comment/PhabricatorAuditCommentEditor.php index a274b2221a..79bf2b3623 100644 --- a/src/applications/audit/editor/comment/PhabricatorAuditCommentEditor.php +++ b/src/applications/audit/editor/comment/PhabricatorAuditCommentEditor.php @@ -1,159 +1,261 @@ commit = $commit; return $this; } public function setUser(PhabricatorUser $user) { $this->user = $user; return $this; } public function addComment(PhabricatorAuditComment $comment) { $commit = $this->commit; $user = $this->user; + $other_comments = id(new PhabricatorAuditComment())->loadAllWhere( + 'targetPHID = %s', + $commit->getPHID()); + $comment ->setActorPHID($user->getPHID()) ->setTargetPHID($commit->getPHID()) ->save(); // When a user submits an audit comment, we update all the audit requests // they have authority over to reflect the most recent status. The general // idea here is that if audit has triggered for, e.g., several packages, but // a user owns all of them, they can clear the audit requirement in one go // without auditing the commit for each trigger. $audit_phids = self::loadAuditPHIDsForUser($this->user); $audit_phids = array_fill_keys($audit_phids, true); $relationships = id(new PhabricatorOwnersPackageCommitRelationship()) ->loadAllWhere( 'commitPHID = %s', $commit->getPHID()); $action = $comment->getAction(); $status_map = PhabricatorAuditActionConstants::getStatusNameMap(); $status = idx($status_map, $action, null); // Status may be empty for updates which don't affect status, like // "comment". $have_any_relationship = false; foreach ($relationships as $relationship) { if (empty($audit_phids[$relationship->getPackagePHID()])) { continue; } $have_any_relationship = true; if ($status) { $relationship->setAuditStatus($status); $relationship->save(); } } if (!$have_any_relationship) { // If the user has no current authority over any audit trigger, make a // new one to represent their audit state. $relationship = id(new PhabricatorOwnersPackageCommitRelationship()) ->setCommitPHID($commit->getPHID()) ->setPackagePHID($user->getPHID()) ->setAuditStatus( $status ? $status : PhabricatorAuditStatusConstants::AUDIT_NOT_REQUIRED) ->setAuditReasons(array("Voluntary Participant")) ->save(); } $this->publishFeedStory($comment, array_keys($audit_phids)); PhabricatorSearchCommitIndexer::indexCommit($commit); - // TODO: Email. + $this->sendMail($comment, $other_comments); } /** * Load the PHIDs for all objects the user has the authority to act as an * audit for. This includes themselves, and any packages they are an owner * of. */ public static function loadAuditPHIDsForUser(PhabricatorUser $user) { $phids = array(); // The user can audit on their own behalf. $phids[$user->getPHID()] = true; // The user can audit on behalf of all packages they own. $owned_packages = id(new PhabricatorOwnersOwner())->loadAllWhere( 'userPHID = %s', $user->getPHID()); if ($owned_packages) { $packages = id(new PhabricatorOwnersPackage())->loadAllWhere( 'id IN (%Ld)', mpull($owned_packages, 'getPackageID')); foreach (mpull($packages, 'getPHID') as $phid) { $phids[$phid] = true; } } // The user can audit on behalf of all projects they are a member of. $query = new PhabricatorProjectQuery(); $query->setMembers(array($user->getPHID())); $projects = $query->execute(); foreach ($projects as $project) { $phids[$project->getPHID()] = true; } return array_keys($phids); } private function publishFeedStory( PhabricatorAuditComment $comment, array $more_phids) { $commit = $this->commit; $user = $this->user; $related_phids = array_merge( array( $user->getPHID(), $commit->getPHID(), ), $more_phids); id(new PhabricatorFeedStoryPublisher()) ->setRelatedPHIDs($related_phids) ->setStoryAuthorPHID($user->getPHID()) ->setStoryTime(time()) ->setStoryType(PhabricatorFeedStoryTypeConstants::STORY_AUDIT) ->setStoryData( array( 'commitPHID' => $commit->getPHID(), 'action' => $comment->getAction(), 'content' => $comment->getContent(), )) ->publish(); } + private function sendMail( + PhabricatorAuditComment $comment, + array $other_comments) { + $commit = $this->commit; + + $data = $commit->loadCommitData(); + $summary = $data->getSummary(); + + $commit_phid = $commit->getPHID(); + $phids = array($commit_phid); + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + $handle = $handles[$commit_phid]; + + $name = $handle->getName(); + + $map = array( + PhabricatorAuditActionConstants::CONCERN => 'Raised Concern', + PhabricatorAuditActionConstants::ACCEPT => 'Accepted', + ); + $verb = idx($map, $comment->getAction(), 'Commented On'); + + $prefix = PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix'); + $subject = "{$prefix} [{$verb}] {$name}: {$summary}"; + $thread_id = 'getPHID().'>'; + $is_new = !count($other_comments); + $body = $this->renderMailBody( + $comment, + "{$name}: {$summary}", + $handle); + + $email_to = array(); + + $author_phid = $data->getCommitDetail('authorPHID'); + if ($author_phid) { + $email_to[] = $author_phid; + } + + $email_cc = array(); + foreach ($other_comments as $comment) { + $email_cc[] = $comment->getActorPHID(); + } + + $phids = array_merge($email_to, $email_cc); + $handles = id(new PhabricatorObjectHandleData($phids))->loadHandles(); + + $template = id(new PhabricatorMetaMTAMail()) + ->setSubject($subject) + ->setFrom($comment->getActorPHID()) + ->addHeader('Thread-Topic', 'Diffusion Audit '.$commit->getPHID()) + ->setThreadID($thread_id, $is_new) + ->setRelatedPHID($commit->getPHID()) + ->setIsBulk(true) + ->setBody($body); + + $reply_handler = self::newReplyHandlerForCommit($commit); + + $mails = $reply_handler->multiplexMail( + $template, + array_select_keys($handles, $email_to), + array_select_keys($handles, $email_cc)); + + foreach ($mails as $mail) { + $mail->saveAndSend(); + } + } + + public static function newReplyHandlerForCommit($commit) { + $handler_class = PhabricatorEnv::getEnvConfig( + 'metamta.diffusion.reply-handler'); + $reply_handler = newv($handler_class, array()); + $reply_handler->setMailReceiver($commit); + return $reply_handler; + } + + private function renderMailBody( + PhabricatorAuditComment $comment, + $cname, + PhabricatorObjectHandle $handle) { + + $commit = $this->commit; + $user = $this->user; + $name = $user->getUsername(); + + $verb = PhabricatorAuditActionConstants::getActionPastTenseVerb( + $comment->getAction()); + + $body = array(); + $body[] = "{$name} {$verb} commit {$cname}."; + + if ($comment->getContent()) { + $body[] = $comment->getContent(); + } + + $body[] = "COMMIT\n ".PhabricatorEnv::getProductionURI($handle->getURI()); + + return implode("\n\n", $body)."\n"; + } + } diff --git a/src/applications/audit/editor/comment/__init__.php b/src/applications/audit/editor/comment/__init__.php index 4fa8bbf9cf..08dfaf2fc3 100644 --- a/src/applications/audit/editor/comment/__init__.php +++ b/src/applications/audit/editor/comment/__init__.php @@ -1,22 +1,26 @@ getDefaultPrivateReplyHandlerEmailAddress($handle, 'C'); + } + + public function getPublicReplyHandlerEmailAddress() { + return $this->getDefaultPublicReplyHandlerEmailAddress('C'); + } + + public function getReplyHandlerDomain() { + return PhabricatorEnv::getEnvConfig( + 'metamta.diffusion.reply-handler-domain'); + } + + public function getReplyHandlerInstructions() { + if ($this->supportsReplies()) { + return "Reply to comment."; + } else { + return null; + } + } + + public function receiveEmail(PhabricatorMetaMTAReceivedMail $mail) { + $commit = $this->getMailReceiver(); + $actor = $this->getActor(); + + // TODO: Support !raise, !accept, etc. + // TODO: Content sources. + + $comment = id(new PhabricatorAuditComment()) + ->setAction(PhabricatorAuditActionConstants::COMMENT) + ->setContent($mail->getCleanTextBody()); + + $editor = new PhabricatorAuditCommentEditor($commit); + $editor->setUser($actor); + $editor->addComment($comment); + } + +} diff --git a/src/applications/audit/replyhandler/__init__.php b/src/applications/audit/replyhandler/__init__.php new file mode 100644 index 0000000000..f584318422 --- /dev/null +++ b/src/applications/audit/replyhandler/__init__.php @@ -0,0 +1,18 @@ +validateMailReceiver($mail_receiver); $this->mailReceiver = $mail_receiver; return $this; } final public function getMailReceiver() { return $this->mailReceiver; } final public function setActor(PhabricatorUser $actor) { $this->actor = $actor; return $this; } final public function getActor() { return $this->actor; } abstract public function validateMailReceiver($mail_receiver); abstract public function getPrivateReplyHandlerEmailAddress( PhabricatorObjectHandle $handle); abstract public function getReplyHandlerDomain(); abstract public function getReplyHandlerInstructions(); abstract public function receiveEmail(PhabricatorMetaMTAReceivedMail $mail); public function supportsPrivateReplies() { return (bool)$this->getReplyHandlerDomain() && !$this->supportsPublicReplies(); } public function supportsPublicReplies() { if (!PhabricatorEnv::getEnvConfig('metamta.public-replies')) { return false; } + if (!$this->getReplyHandlerDomain()) { + return false; + } return (bool)$this->getPublicReplyHandlerEmailAddress(); } final public function supportsReplies() { return $this->supportsPrivateReplies() || $this->supportsPublicReplies(); } public function getPublicReplyHandlerEmailAddress() { return null; } final public function multiplexMail( PhabricatorMetaMTAMail $mail_template, array $to_handles, array $cc_handles) { $result = array(); // If private replies are not supported, simply send one email to all // recipients and CCs. This covers cases where we have no reply handler, // or we have a public reply handler. if (!$this->supportsPrivateReplies()) { $mail = clone $mail_template; $mail->addTos(mpull($to_handles, 'getPHID')); $mail->addCCs(mpull($cc_handles, 'getPHID')); if ($this->supportsPublicReplies()) { $reply_to = $this->getPublicReplyHandlerEmailAddress(); $mail->setReplyTo($reply_to); } $result[] = $mail; return $result; } // Merge all the recipients together. TODO: We could keep the CCs as real // CCs and send to a "noreply@domain.com" type address, but keep it simple // for now. $recipients = mpull($to_handles, null, 'getPHID') + mpull($cc_handles, null, 'getPHID'); // This grouping is just so we can use the public reply-to for any // recipients without a private reply-to, e.g. mailing lists. $groups = array(); foreach ($recipients as $recipient) { $private = $this->getPrivateReplyHandlerEmailAddress($recipient); $groups[$private][] = $recipient; } // When multiplexing mail, explicitly include To/Cc information in the // message body and headers. $add_headers = array(); $body = $mail_template->getBody(); $body .= "\n"; if ($to_handles) { $body .= "To: ".implode(', ', mpull($to_handles, 'getName'))."\n"; $add_headers['X-Phabricator-To'] = $this->formatPHIDList($to_handles); } if ($cc_handles) { $body .= "Cc: ".implode(', ', mpull($cc_handles, 'getName'))."\n"; $add_headers['X-Phabricator-Cc'] = $this->formatPHIDList($cc_handles); } foreach ($groups as $reply_to => $group) { $mail = clone $mail_template; $mail->addTos(mpull($group, 'getPHID')); $mail->setBody($body); foreach ($add_headers as $header => $value) { $mail->addHeader($header, $value); } if (!$reply_to && $this->supportsPublicReplies()) { $reply_to = $this->getPublicReplyHandlerEmailAddress(); } if ($reply_to) { $mail->setReplyTo($reply_to); } $result[] = $mail; } return $result; } protected function formatPHIDList(array $handles) { $list = array(); foreach ($handles as $handle) { $list[] = '<'.$handle->getPHID().'>'; } return implode(', ', $list); } protected function getDefaultPublicReplyHandlerEmailAddress($prefix) { $receiver = $this->getMailReceiver(); $receiver_id = $receiver->getID(); $domain = $this->getReplyHandlerDomain(); // We compute a hash using the object's own PHID to prevent an attacker // from blindly interacting with objects that they haven't ever received // mail about by just sending to D1@, D2@, etc... $hash = PhabricatorMetaMTAReceivedMail::computeMailHash( $receiver->getMailKey(), $receiver->getPHID()); $address = "{$prefix}{$receiver_id}+public+{$hash}@{$domain}"; return $this->getSingleReplyHandlerPrefix($address); } protected function getSingleReplyHandlerPrefix($address) { $single_handle_prefix = PhabricatorEnv::getEnvConfig( 'metamta.single-reply-handler-prefix'); return ($single_handle_prefix) ? $single_handle_prefix . '+' . $address : $address; } protected function getDefaultPrivateReplyHandlerEmailAddress( PhabricatorObjectHandle $handle, $prefix) { if ($handle->getType() != PhabricatorPHIDConstants::PHID_TYPE_USER) { // You must be a real user to get a private reply handler address. return null; } $receiver = $this->getMailReceiver(); $receiver_id = $receiver->getID(); $user_id = $handle->getAlternateID(); $hash = PhabricatorMetaMTAReceivedMail::computeMailHash( $receiver->getMailKey(), $handle->getPHID()); $domain = $this->getReplyHandlerDomain(); $address = "{$prefix}{$receiver_id}+{$user_id}+{$hash}@{$domain}"; return $this->getSingleReplyHandlerPrefix($address); } } diff --git a/src/applications/metamta/storage/receivedmail/PhabricatorMetaMTAReceivedMail.php b/src/applications/metamta/storage/receivedmail/PhabricatorMetaMTAReceivedMail.php index 7f83330bd9..5cbb63b97e 100644 --- a/src/applications/metamta/storage/receivedmail/PhabricatorMetaMTAReceivedMail.php +++ b/src/applications/metamta/storage/receivedmail/PhabricatorMetaMTAReceivedMail.php @@ -1,293 +1,299 @@ array( 'headers' => self::SERIALIZATION_JSON, 'bodies' => self::SERIALIZATION_JSON, 'attachments' => self::SERIALIZATION_JSON, ), ) + parent::getConfiguration(); } public function setHeaders(array $headers) { // Normalize headers to lowercase. $normalized = array(); foreach ($headers as $name => $value) { $normalized[strtolower($name)] = $value; } $this->headers = $normalized; return $this; } public function getMessageID() { return idx($this->headers, 'message-id'); } public function getSubject() { return idx($this->headers, 'subject'); } public function processReceivedMail() { $to = idx($this->headers, 'to'); $to = $this->getRawEmailAddress($to); $from = idx($this->headers, 'from'); $create_task = PhabricatorEnv::getEnvConfig( 'metamta.maniphest.public-create-email'); if ($create_task && $to == $create_task) { $receiver = new ManiphestTask(); $user = $this->lookupPublicUser(); if ($user) { $this->setAuthorPHID($user->getPHID()); } else { $default_author = PhabricatorEnv::getEnvConfig( 'metamta.maniphest.default-public-author'); if ($default_author) { $user = id(new PhabricatorUser())->loadOneWhere( 'username = %s', $default_author); if ($user) { $receiver->setOriginalEmailSource($from); } else { throw new Exception( "Phabricator is misconfigured, the configuration key ". "'metamta.maniphest.default-public-author' is set to user ". "'{$default_author}' but that user does not exist."); } } else { // TODO: We should probably bounce these since from the user's // perspective their email vanishes into a black hole. return $this->setMessage("Invalid public user '{$from}'.")->save(); } } $receiver->setAuthorPHID($user->getPHID()); $receiver->setPriority(ManiphestTaskPriority::PRIORITY_TRIAGE); $editor = new ManiphestTransactionEditor(); $handler = $editor->buildReplyHandler($receiver); $handler->setActor($user); $handler->receiveEmail($this); $this->setRelatedPHID($receiver->getPHID()); $this->setMessage('OK'); return $this->save(); } // We've already stripped this, so look for an object address which has // a format like: D291+291+b0a41ca848d66dcc@example.com $matches = null; $single_handle_prefix = PhabricatorEnv::getEnvConfig( 'metamta.single-reply-handler-prefix'); $prefixPattern = ($single_handle_prefix) ? preg_quote($single_handle_prefix, '/') . '\+' : ''; - $pattern = "/^{$prefixPattern}((?:D|T)\d+)\+([\w]+)\+([a-f0-9]{16})@/U"; + $pattern = "/^{$prefixPattern}((?:D|T|C)\d+)\+([\w]+)\+([a-f0-9]{16})@/U"; $ok = preg_match( $pattern, $to, $matches); if (!$ok) { return $this->setMessage("Unrecognized 'to' format: {$to}")->save(); } $receiver_name = $matches[1]; $user_id = $matches[2]; $hash = $matches[3]; if ($user_id == 'public') { if (!PhabricatorEnv::getEnvConfig('metamta.public-replies')) { return $this->setMessage("Public replies not enabled.")->save(); } $user = $this->lookupPublicUser(); if (!$user) { return $this->setMessage("Invalid public user '{$from}'.")->save(); } $use_user_hash = false; } else { $user = id(new PhabricatorUser())->load($user_id); if (!$user) { return $this->setMessage("Invalid private user '{$user_id}'.")->save(); } $use_user_hash = true; } if ($user->getIsDisabled()) { return $this->setMessage("User '{$user_id}' is disabled")->save(); } $this->setAuthorPHID($user->getPHID()); $receiver = self::loadReceiverObject($receiver_name); if (!$receiver) { return $this->setMessage("Invalid object '{$receiver_name}'")->save(); } $this->setRelatedPHID($receiver->getPHID()); if ($use_user_hash) { // This is a private reply-to address, check that the user hash is // correct. $check_phid = $user->getPHID(); } else { // This is a public reply-to address, check that the object hash is // correct. $check_phid = $receiver->getPHID(); } $expect_hash = self::computeMailHash($receiver->getMailKey(), $check_phid); // See note at computeOldMailHash(). $old_hash = self::computeOldMailHash($receiver->getMailKey(), $check_phid); if ($expect_hash != $hash && $old_hash != $hash) { return $this->setMessage("Invalid mail hash!")->save(); } if ($receiver instanceof ManiphestTask) { $editor = new ManiphestTransactionEditor(); $handler = $editor->buildReplyHandler($receiver); } else if ($receiver instanceof DifferentialRevision) { $handler = DifferentialMail::newReplyHandlerForRevision($receiver); + } else if ($receiver instanceof PhabricatorRepositoryCommit) { + $handler = PhabricatorAuditCommentEditor::newReplyHandlerForCommit( + $receiver); } $handler->setActor($user); $handler->receiveEmail($this); $this->setMessage('OK'); return $this->save(); } public function getCleanTextBody() { $body = idx($this->bodies, 'text'); $parser = new PhabricatorMetaMTAEmailBodyParser($body); return $parser->stripQuotedText(); } public static function loadReceiverObject($receiver_name) { if (!$receiver_name) { return null; } $receiver_type = $receiver_name[0]; $receiver_id = substr($receiver_name, 1); $class_obj = null; switch ($receiver_type) { case 'T': $class_obj = newv('ManiphestTask', array()); break; case 'D': $class_obj = newv('DifferentialRevision', array()); break; + case 'C': + $class_obj = newv('PhabricatorRepositoryCommit', array()); + break; default: return null; } return $class_obj->load($receiver_id); } public static function computeMailHash($mail_key, $phid) { $global_mail_key = PhabricatorEnv::getEnvConfig('phabricator.mail-key'); $hash = PhabricatorHash::digest($mail_key.$global_mail_key.$phid); return substr($hash, 0, 16); } public static function computeOldMailHash($mail_key, $phid) { // TODO: Remove this method entirely in a couple of months. We've moved from // plain sha1 to sha1+hmac to make the codebase more auditable for good uses // of hash functions, but still accept the old hashes on email replies to // avoid breaking things. Once we've been sending only hmac hashes for a // while, remove this and start rejecting old hashes. See T547. $global_mail_key = PhabricatorEnv::getEnvConfig('phabricator.mail-key'); $hash = sha1($mail_key.$global_mail_key.$phid); return substr($hash, 0, 16); } /** * Strip an email address down to the actual user@domain.tld part if * necessary, since sometimes it will have formatting like * '"Abraham Lincoln" '. */ private function getRawEmailAddress($address) { $matches = null; $ok = preg_match('/<(.*)>/', $address, $matches); if ($ok) { $address = $matches[1]; } return $address; } private function lookupPublicUser() { $from = idx($this->headers, 'from'); $from = $this->getRawEmailAddress($from); $user = id(new PhabricatorUser())->loadOneWhere( 'email = %s', $from); // If Phabricator is configured to allow "Reply-To" authentication, try // the "Reply-To" address if we failed to match the "From" address. $config_key = 'metamta.insecure-auth-with-reply-to'; $allow_reply_to = PhabricatorEnv::getEnvConfig($config_key); if (!$user && $allow_reply_to) { $reply_to = idx($this->headers, 'reply-to'); $reply_to = $this->getRawEmailAddress($reply_to); if ($reply_to) { $user = id(new PhabricatorUser())->loadOneWhere( 'email = %s', $reply_to); } } return $user; } } diff --git a/src/applications/metamta/storage/receivedmail/__init__.php b/src/applications/metamta/storage/receivedmail/__init__.php index 37d4e56863..b5100b8dea 100644 --- a/src/applications/metamta/storage/receivedmail/__init__.php +++ b/src/applications/metamta/storage/receivedmail/__init__.php @@ -1,22 +1,23 @@ true, self::CONFIG_TIMESTAMPS => false, ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID( PhabricatorPHIDConstants::PHID_TYPE_CMIT); } public function loadCommitData() { if (!$this->getID()) { return null; } return id(new PhabricatorRepositoryCommitData())->loadOneWhere( 'commitID = %d', $this->getID()); } public function attachCommitData(PhabricatorRepositoryCommitData $data) { $this->commitData = $data; return $this; } public function getCommitData() { if (!$this->commitData) { throw new Exception("Attach commit data with attachCommitData() first!"); } return $this->commitData; } + public function getMailKey() { + // TODO: Fix properly! + return $this->phid; + } + public function delete() { $data = $this->loadCommitData(); $this->openTransaction(); if ($data) { $data->delete(); } $result = parent::delete(); $this->saveTransaction(); return $result; } }