1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-10 06:41:04 +01:00

(stable) Promote 2019 Week 3

This commit is contained in:
epriestley 2019-01-18 20:11:53 -08:00
commit 9ac1b05398
168 changed files with 5211 additions and 2321 deletions

View file

@ -42,6 +42,102 @@ if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PH
class PHPMailerLite { class PHPMailerLite {
public static function newFromMessage(
PhabricatorMailExternalMessage $message) {
$mailer = new self($use_exceptions = true);
// By default, PHPMailerLite sends one mail per recipient. We handle
// combining or separating To and Cc higher in the stack, so tell it to
// send mail exactly like we ask.
$mailer->SingleTo = false;
$mailer->CharSet = 'utf-8';
$mailer->Encoding = 'base64';
$subject = $message->getSubject();
if ($subject !== null) {
$mailer->Subject = $subject;
}
$from_address = $message->getFromAddress();
if ($from_address) {
$mailer->SetFrom(
$from_address->getAddress(),
(string)$from_address->getDisplayName(),
$crazy_side_effects = false);
}
$reply_address = $message->getReplyToAddress();
if ($reply_address) {
$mailer->AddReplyTo(
$reply_address->getAddress(),
(string)$reply_address->getDisplayName());
}
$to_addresses = $message->getToAddresses();
if ($to_addresses) {
foreach ($to_addresses as $address) {
$mailer->AddAddress(
$address->getAddress(),
(string)$address->getDisplayName());
}
}
$cc_addresses = $message->getCCAddresses();
if ($cc_addresses) {
foreach ($cc_addresses as $address) {
$mailer->AddCC(
$address->getAddress(),
(string)$address->getDisplayName());
}
}
$headers = $message->getHeaders();
if ($headers) {
foreach ($headers as $header) {
$name = $header->getName();
$value = $header->getValue();
if (phutil_utf8_strtolower($name) === 'message-id') {
$mailer->MessageID = $value;
} else {
$mailer->AddCustomHeader("{$name}: {$value}");
}
}
}
$attachments = $message->getAttachments();
if ($attachments) {
foreach ($attachments as $attachment) {
$mailer->AddStringAttachment(
$attachment->getData(),
$attachment->getFilename(),
'base64',
$attachment->getMimeType());
}
}
$text_body = $message->getTextBody();
if ($text_body !== null) {
$mailer->Body = $text_body;
}
$html_body = $message->getHTMLBody();
if ($html_body !== null) {
$mailer->IsHTML(true);
$mailer->Body = $html_body;
if ($text_body !== null) {
$mailer->AltBody = $text_body;
}
}
return $mailer;
}
///////////////////////////////////////////////// /////////////////////////////////////////////////
// PROPERTIES, PUBLIC // PROPERTIES, PUBLIC
///////////////////////////////////////////////// /////////////////////////////////////////////////

View file

@ -9,7 +9,7 @@ return array(
'names' => array( 'names' => array(
'conpherence.pkg.css' => '3c8a0668', 'conpherence.pkg.css' => '3c8a0668',
'conpherence.pkg.js' => '020aebcf', 'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => '7fa376a9', 'core.pkg.css' => 'e94cc920',
'core.pkg.js' => '5c737607', 'core.pkg.js' => '5c737607',
'differential.pkg.css' => 'b8df73d4', 'differential.pkg.css' => 'b8df73d4',
'differential.pkg.js' => '67c9ea4c', 'differential.pkg.js' => '67c9ea4c',
@ -36,7 +36,7 @@ return array(
'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2', 'rsrc/css/aphront/typeahead-browse.css' => 'b7ed02d2',
'rsrc/css/aphront/typeahead.css' => '8779483d', 'rsrc/css/aphront/typeahead.css' => '8779483d',
'rsrc/css/application/almanac/almanac.css' => '2e050f4f', 'rsrc/css/application/almanac/almanac.css' => '2e050f4f',
'rsrc/css/application/auth/auth.css' => '9f6e4ed8', 'rsrc/css/application/auth/auth.css' => 'add92fd8',
'rsrc/css/application/base/main-menu-view.css' => '8e2d9a28', 'rsrc/css/application/base/main-menu-view.css' => '8e2d9a28',
'rsrc/css/application/base/notification-menu.css' => 'e6962e89', 'rsrc/css/application/base/notification-menu.css' => 'e6962e89',
'rsrc/css/application/base/phui-theme.css' => '35883b37', 'rsrc/css/application/base/phui-theme.css' => '35883b37',
@ -91,7 +91,7 @@ return array(
'rsrc/css/application/pholio/pholio-inline-comments.css' => '722b48c2', 'rsrc/css/application/pholio/pholio-inline-comments.css' => '722b48c2',
'rsrc/css/application/pholio/pholio.css' => '88ef5ef1', 'rsrc/css/application/pholio/pholio.css' => '88ef5ef1',
'rsrc/css/application/phortune/phortune-credit-card-form.css' => '3b9868a8', 'rsrc/css/application/phortune/phortune-credit-card-form.css' => '3b9868a8',
'rsrc/css/application/phortune/phortune-invoice.css' => 'e41765fc', 'rsrc/css/application/phortune/phortune-invoice.css' => '4436b241',
'rsrc/css/application/phortune/phortune.css' => '12e8251a', 'rsrc/css/application/phortune/phortune.css' => '12e8251a',
'rsrc/css/application/phrequent/phrequent.css' => 'bd79cc67', 'rsrc/css/application/phrequent/phrequent.css' => 'bd79cc67',
'rsrc/css/application/phriction/phriction-document-css.css' => '03380da0', 'rsrc/css/application/phriction/phriction-document-css.css' => '03380da0',
@ -395,7 +395,7 @@ return array(
'rsrc/js/application/herald/PathTypeahead.js' => 'ad486db3', 'rsrc/js/application/herald/PathTypeahead.js' => 'ad486db3',
'rsrc/js/application/herald/herald-rule-editor.js' => '0922e81d', 'rsrc/js/application/herald/herald-rule-editor.js' => '0922e81d',
'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'cffd39b4', 'rsrc/js/application/maniphest/behavior-batch-selector.js' => 'cffd39b4',
'rsrc/js/application/maniphest/behavior-line-chart.js' => '3e9da12d', 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'c8147a20',
'rsrc/js/application/maniphest/behavior-list-edit.js' => 'c687e867', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'c687e867',
'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '8400307c', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '8400307c',
'rsrc/js/application/owners/OwnersPathEditor.js' => '2a8b62d9', 'rsrc/js/application/owners/OwnersPathEditor.js' => '2a8b62d9',
@ -524,7 +524,7 @@ return array(
'aphront-tooltip-css' => 'e3f2412f', 'aphront-tooltip-css' => 'e3f2412f',
'aphront-typeahead-control-css' => '8779483d', 'aphront-typeahead-control-css' => '8779483d',
'application-search-view-css' => '0f7c06d8', 'application-search-view-css' => '0f7c06d8',
'auth-css' => '9f6e4ed8', 'auth-css' => 'add92fd8',
'bulk-job-css' => '73af99f5', 'bulk-job-css' => '73af99f5',
'conduit-api-css' => 'ce2cfc41', 'conduit-api-css' => 'ce2cfc41',
'config-options-css' => '16c920ae', 'config-options-css' => '16c920ae',
@ -614,7 +614,7 @@ return array(
'javelin-behavior-icon-composer' => '38a6cedb', 'javelin-behavior-icon-composer' => '38a6cedb',
'javelin-behavior-launch-icon-composer' => 'a17b84f1', 'javelin-behavior-launch-icon-composer' => 'a17b84f1',
'javelin-behavior-lightbox-attachments' => 'c7e748bf', 'javelin-behavior-lightbox-attachments' => 'c7e748bf',
'javelin-behavior-line-chart' => '3e9da12d', 'javelin-behavior-line-chart' => 'c8147a20',
'javelin-behavior-linked-container' => '74446546', 'javelin-behavior-linked-container' => '74446546',
'javelin-behavior-maniphest-batch-selector' => 'cffd39b4', 'javelin-behavior-maniphest-batch-selector' => 'cffd39b4',
'javelin-behavior-maniphest-list-editor' => 'c687e867', 'javelin-behavior-maniphest-list-editor' => 'c687e867',
@ -788,7 +788,7 @@ return array(
'phortune-credit-card-form' => 'd12d214f', 'phortune-credit-card-form' => 'd12d214f',
'phortune-credit-card-form-css' => '3b9868a8', 'phortune-credit-card-form-css' => '3b9868a8',
'phortune-css' => '12e8251a', 'phortune-css' => '12e8251a',
'phortune-invoice-css' => 'e41765fc', 'phortune-invoice-css' => '4436b241',
'phrequent-css' => 'bd79cc67', 'phrequent-css' => 'bd79cc67',
'phriction-document-css' => '03380da0', 'phriction-document-css' => '03380da0',
'phui-action-panel-css' => '6c386cbf', 'phui-action-panel-css' => '6c386cbf',
@ -1200,12 +1200,6 @@ return array(
'javelin-vector', 'javelin-vector',
'javelin-dom', 'javelin-dom',
), ),
'3e9da12d' => array(
'javelin-behavior',
'javelin-dom',
'javelin-vector',
'phui-chart-css',
),
'3eed1f2b' => array( '3eed1f2b' => array(
'javelin-behavior', 'javelin-behavior',
'javelin-stratcom', 'javelin-stratcom',
@ -1950,6 +1944,12 @@ return array(
'phuix-icon-view', 'phuix-icon-view',
'phabricator-busy', 'phabricator-busy',
), ),
'c8147a20' => array(
'javelin-behavior',
'javelin-dom',
'javelin-vector',
'phui-chart-css',
),
'c9749dcd' => array( 'c9749dcd' => array(
'javelin-install', 'javelin-install',
'javelin-util', 'javelin-util',

View file

@ -0,0 +1,9 @@
CREATE TABLE {$NAMESPACE}_auth.auth_factorprovider (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
providerFactorKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
properties LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,19 @@
CREATE TABLE {$NAMESPACE}_auth.auth_factorprovidertransaction (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
authorPHID VARBINARY(64) NOT NULL,
objectPHID VARBINARY(64) NOT NULL,
viewPolicy VARBINARY(64) NOT NULL,
editPolicy VARBINARY(64) NOT NULL,
commentPHID VARBINARY(64) DEFAULT NULL,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) NOT NULL,
oldValue LONGTEXT NOT NULL,
newValue LONGTEXT NOT NULL,
contentSource LONGTEXT NOT NULL,
metadata LONGTEXT NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (`phid`),
KEY `key_object` (`objectPHID`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_auth.auth_factorprovider
ADD name VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,3 @@
ALTER TABLE {$NAMESPACE}_phortune.phortune_account
ADD billingName VARCHAR(255) NOT NULL COLLATE {$COLLATE_TEXT},
ADD billingAddress LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,8 @@
CREATE TABLE {$NAMESPACE}_auth.auth_message (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
messageKey VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
messageText LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -0,0 +1,19 @@
CREATE TABLE {$NAMESPACE}_auth.auth_messagetransaction (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
authorPHID VARBINARY(64) NOT NULL,
objectPHID VARBINARY(64) NOT NULL,
viewPolicy VARBINARY(64) NOT NULL,
editPolicy VARBINARY(64) NOT NULL,
commentPHID VARBINARY(64) DEFAULT NULL,
commentVersion INT UNSIGNED NOT NULL,
transactionType VARCHAR(32) NOT NULL,
oldValue LONGTEXT NOT NULL,
newValue LONGTEXT NOT NULL,
contentSource LONGTEXT NOT NULL,
metadata LONGTEXT NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_phid` (`phid`),
KEY `key_object` (`objectPHID`)
) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT};

View file

@ -110,9 +110,9 @@ function commit_symbols(
$conn_w, $conn_w,
'INSERT INTO %T 'INSERT INTO %T
(repositoryPHID, symbolContext, symbolName, symbolType, (repositoryPHID, symbolContext, symbolName, symbolType,
symbolLanguage, lineNumber, pathID) VALUES %Q', symbolLanguage, lineNumber, pathID) VALUES %LQ',
$symbol->getTableName(), $symbol->getTableName(),
implode(', ', $chunk)); $chunk);
} }
} }

View file

@ -59,7 +59,12 @@ id(new PhabricatorUserEditor())
->setActor($admin) ->setActor($admin)
->createNewUser($user, $email_object); ->createNewUser($user, $email_object);
$user->sendWelcomeEmail($admin); $welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
->setSender($admin)
->setRecipient($user);
if ($welcome_engine->canSendMail()) {
$welcome_engine->sendMail();
}
echo pht( echo pht(
"Created user '%s' (realname='%s', email='%s').\n", "Created user '%s' (realname='%s', email='%s').\n",

View file

@ -341,7 +341,6 @@ phutil_register_library_map(array(
'ConduitWildParameterType' => 'applications/conduit/parametertype/ConduitWildParameterType.php', 'ConduitWildParameterType' => 'applications/conduit/parametertype/ConduitWildParameterType.php',
'ConpherenceColumnViewController' => 'applications/conpherence/controller/ConpherenceColumnViewController.php', 'ConpherenceColumnViewController' => 'applications/conpherence/controller/ConpherenceColumnViewController.php',
'ConpherenceConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceConduitAPIMethod.php', 'ConpherenceConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceConduitAPIMethod.php',
'ConpherenceConfigOptions' => 'applications/conpherence/config/ConpherenceConfigOptions.php',
'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php', 'ConpherenceConstants' => 'applications/conpherence/constants/ConpherenceConstants.php',
'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php', 'ConpherenceController' => 'applications/conpherence/controller/ConpherenceController.php',
'ConpherenceCreateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php', 'ConpherenceCreateThreadConduitAPIMethod' => 'applications/conpherence/conduit/ConpherenceCreateThreadConduitAPIMethod.php',
@ -2190,6 +2189,7 @@ phutil_register_library_map(array(
'PhabricatorAuthAccountView' => 'applications/auth/view/PhabricatorAuthAccountView.php', 'PhabricatorAuthAccountView' => 'applications/auth/view/PhabricatorAuthAccountView.php',
'PhabricatorAuthApplication' => 'applications/auth/application/PhabricatorAuthApplication.php', 'PhabricatorAuthApplication' => 'applications/auth/application/PhabricatorAuthApplication.php',
'PhabricatorAuthAuthFactorPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php', 'PhabricatorAuthAuthFactorPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorPHIDType.php',
'PhabricatorAuthAuthFactorProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthFactorProviderPHIDType.php',
'PhabricatorAuthAuthProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php', 'PhabricatorAuthAuthProviderPHIDType' => 'applications/auth/phid/PhabricatorAuthAuthProviderPHIDType.php',
'PhabricatorAuthCSRFEngine' => 'applications/auth/engine/PhabricatorAuthCSRFEngine.php', 'PhabricatorAuthCSRFEngine' => 'applications/auth/engine/PhabricatorAuthCSRFEngine.php',
'PhabricatorAuthChallenge' => 'applications/auth/storage/PhabricatorAuthChallenge.php', 'PhabricatorAuthChallenge' => 'applications/auth/storage/PhabricatorAuthChallenge.php',
@ -2207,6 +2207,18 @@ phutil_register_library_map(array(
'PhabricatorAuthEditController' => 'applications/auth/controller/config/PhabricatorAuthEditController.php', 'PhabricatorAuthEditController' => 'applications/auth/controller/config/PhabricatorAuthEditController.php',
'PhabricatorAuthFactor' => 'applications/auth/factor/PhabricatorAuthFactor.php', 'PhabricatorAuthFactor' => 'applications/auth/factor/PhabricatorAuthFactor.php',
'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php', 'PhabricatorAuthFactorConfig' => 'applications/auth/storage/PhabricatorAuthFactorConfig.php',
'PhabricatorAuthFactorProvider' => 'applications/auth/storage/PhabricatorAuthFactorProvider.php',
'PhabricatorAuthFactorProviderController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderController.php',
'PhabricatorAuthFactorProviderEditController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderEditController.php',
'PhabricatorAuthFactorProviderEditEngine' => 'applications/auth/editor/PhabricatorAuthFactorProviderEditEngine.php',
'PhabricatorAuthFactorProviderEditor' => 'applications/auth/editor/PhabricatorAuthFactorProviderEditor.php',
'PhabricatorAuthFactorProviderListController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderListController.php',
'PhabricatorAuthFactorProviderNameTransaction' => 'applications/auth/xaction/PhabricatorAuthFactorProviderNameTransaction.php',
'PhabricatorAuthFactorProviderQuery' => 'applications/auth/query/PhabricatorAuthFactorProviderQuery.php',
'PhabricatorAuthFactorProviderTransaction' => 'applications/auth/storage/PhabricatorAuthFactorProviderTransaction.php',
'PhabricatorAuthFactorProviderTransactionQuery' => 'applications/auth/query/PhabricatorAuthFactorProviderTransactionQuery.php',
'PhabricatorAuthFactorProviderTransactionType' => 'applications/auth/xaction/PhabricatorAuthFactorProviderTransactionType.php',
'PhabricatorAuthFactorProviderViewController' => 'applications/auth/controller/mfa/PhabricatorAuthFactorProviderViewController.php',
'PhabricatorAuthFactorResult' => 'applications/auth/factor/PhabricatorAuthFactorResult.php', 'PhabricatorAuthFactorResult' => 'applications/auth/factor/PhabricatorAuthFactorResult.php',
'PhabricatorAuthFactorTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTestCase.php', 'PhabricatorAuthFactorTestCase' => 'applications/auth/factor/__tests__/PhabricatorAuthFactorTestCase.php',
'PhabricatorAuthFinishController' => 'applications/auth/controller/PhabricatorAuthFinishController.php', 'PhabricatorAuthFinishController' => 'applications/auth/controller/PhabricatorAuthFinishController.php',
@ -2234,6 +2246,7 @@ phutil_register_library_map(array(
'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php', 'PhabricatorAuthListController' => 'applications/auth/controller/config/PhabricatorAuthListController.php',
'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php',
'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php', 'PhabricatorAuthLoginHandler' => 'applications/auth/handler/PhabricatorAuthLoginHandler.php',
'PhabricatorAuthLoginMessageType' => 'applications/auth/message/PhabricatorAuthLoginMessageType.php',
'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php', 'PhabricatorAuthLogoutConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthLogoutConduitAPIMethod.php',
'PhabricatorAuthMFAEditEngineExtension' => 'applications/auth/engineextension/PhabricatorAuthMFAEditEngineExtension.php', 'PhabricatorAuthMFAEditEngineExtension' => 'applications/auth/engineextension/PhabricatorAuthMFAEditEngineExtension.php',
'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php', 'PhabricatorAuthMainMenuBarExtension' => 'applications/auth/extension/PhabricatorAuthMainMenuBarExtension.php',
@ -2249,6 +2262,20 @@ phutil_register_library_map(array(
'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'applications/auth/management/PhabricatorAuthManagementUntrustOAuthClientWorkflow.php',
'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php', 'PhabricatorAuthManagementVerifyWorkflow' => 'applications/auth/management/PhabricatorAuthManagementVerifyWorkflow.php',
'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php', 'PhabricatorAuthManagementWorkflow' => 'applications/auth/management/PhabricatorAuthManagementWorkflow.php',
'PhabricatorAuthMessage' => 'applications/auth/storage/PhabricatorAuthMessage.php',
'PhabricatorAuthMessageController' => 'applications/auth/controller/message/PhabricatorAuthMessageController.php',
'PhabricatorAuthMessageEditController' => 'applications/auth/controller/message/PhabricatorAuthMessageEditController.php',
'PhabricatorAuthMessageEditEngine' => 'applications/auth/editor/PhabricatorAuthMessageEditEngine.php',
'PhabricatorAuthMessageEditor' => 'applications/auth/editor/PhabricatorAuthMessageEditor.php',
'PhabricatorAuthMessageListController' => 'applications/auth/controller/message/PhabricatorAuthMessageListController.php',
'PhabricatorAuthMessagePHIDType' => 'applications/auth/phid/PhabricatorAuthMessagePHIDType.php',
'PhabricatorAuthMessageQuery' => 'applications/auth/query/PhabricatorAuthMessageQuery.php',
'PhabricatorAuthMessageTextTransaction' => 'applications/auth/xaction/PhabricatorAuthMessageTextTransaction.php',
'PhabricatorAuthMessageTransaction' => 'applications/auth/storage/PhabricatorAuthMessageTransaction.php',
'PhabricatorAuthMessageTransactionQuery' => 'applications/auth/query/PhabricatorAuthMessageTransactionQuery.php',
'PhabricatorAuthMessageTransactionType' => 'applications/auth/xaction/PhabricatorAuthMessageTransactionType.php',
'PhabricatorAuthMessageType' => 'applications/auth/message/PhabricatorAuthMessageType.php',
'PhabricatorAuthMessageViewController' => 'applications/auth/controller/message/PhabricatorAuthMessageViewController.php',
'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php', 'PhabricatorAuthNeedsApprovalController' => 'applications/auth/controller/PhabricatorAuthNeedsApprovalController.php',
'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php', 'PhabricatorAuthNeedsMultiFactorController' => 'applications/auth/controller/PhabricatorAuthNeedsMultiFactorController.php',
'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php', 'PhabricatorAuthNewController' => 'applications/auth/controller/config/PhabricatorAuthNewController.php',
@ -2277,6 +2304,7 @@ phutil_register_library_map(array(
'PhabricatorAuthProviderConfigQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigQuery.php', 'PhabricatorAuthProviderConfigQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigQuery.php',
'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php', 'PhabricatorAuthProviderConfigTransaction' => 'applications/auth/storage/PhabricatorAuthProviderConfigTransaction.php',
'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php', 'PhabricatorAuthProviderConfigTransactionQuery' => 'applications/auth/query/PhabricatorAuthProviderConfigTransactionQuery.php',
'PhabricatorAuthProviderController' => 'applications/auth/controller/config/PhabricatorAuthProviderController.php',
'PhabricatorAuthProvidersGuidanceContext' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceContext.php', 'PhabricatorAuthProvidersGuidanceContext' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceContext.php',
'PhabricatorAuthProvidersGuidanceEngineExtension' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php', 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'applications/auth/guidance/PhabricatorAuthProvidersGuidanceEngineExtension.php',
'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthQueryPublicKeysConduitAPIMethod.php', 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'applications/auth/conduit/PhabricatorAuthQueryPublicKeysConduitAPIMethod.php',
@ -2324,6 +2352,7 @@ phutil_register_library_map(array(
'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php', 'PhabricatorAuthTryFactorAction' => 'applications/auth/action/PhabricatorAuthTryFactorAction.php',
'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php', 'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php',
'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php', 'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php',
'PhabricatorAuthWelcomeMailMessageType' => 'applications/auth/message/PhabricatorAuthWelcomeMailMessageType.php',
'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php', 'PhabricatorAuthenticationConfigOptions' => 'applications/config/option/PhabricatorAuthenticationConfigOptions.php',
'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php', 'PhabricatorAutoEventListener' => 'infrastructure/events/PhabricatorAutoEventListener.php',
'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php', 'PhabricatorBadgesApplication' => 'applications/badges/application/PhabricatorBadgesApplication.php',
@ -3319,7 +3348,6 @@ phutil_register_library_map(array(
'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php', 'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php',
'PhabricatorLabelProfileMenuItem' => 'applications/search/menuitem/PhabricatorLabelProfileMenuItem.php', 'PhabricatorLabelProfileMenuItem' => 'applications/search/menuitem/PhabricatorLabelProfileMenuItem.php',
'PhabricatorLegalpadApplication' => 'applications/legalpad/application/PhabricatorLegalpadApplication.php', 'PhabricatorLegalpadApplication' => 'applications/legalpad/application/PhabricatorLegalpadApplication.php',
'PhabricatorLegalpadConfigOptions' => 'applications/legalpad/config/PhabricatorLegalpadConfigOptions.php',
'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php', 'PhabricatorLegalpadDocumentPHIDType' => 'applications/legalpad/phid/PhabricatorLegalpadDocumentPHIDType.php',
'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php', 'PhabricatorLegalpadSignaturePolicyRule' => 'applications/legalpad/policyrule/PhabricatorLegalpadSignaturePolicyRule.php',
'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.php', 'PhabricatorLibraryTestCase' => '__tests__/PhabricatorLibraryTestCase.php',
@ -3348,7 +3376,6 @@ phutil_register_library_map(array(
'PhabricatorMacroAudioBehaviorTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php', 'PhabricatorMacroAudioBehaviorTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioBehaviorTransaction.php',
'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php', 'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php',
'PhabricatorMacroAudioTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioTransaction.php', 'PhabricatorMacroAudioTransaction' => 'applications/macro/xaction/PhabricatorMacroAudioTransaction.php',
'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php',
'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php',
'PhabricatorMacroDatasource' => 'applications/macro/typeahead/PhabricatorMacroDatasource.php', 'PhabricatorMacroDatasource' => 'applications/macro/typeahead/PhabricatorMacroDatasource.php',
'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php', 'PhabricatorMacroDisableController' => 'applications/macro/controller/PhabricatorMacroDisableController.php',
@ -3373,8 +3400,11 @@ phutil_register_library_map(array(
'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php', 'PhabricatorMacroTransactionQuery' => 'applications/macro/query/PhabricatorMacroTransactionQuery.php',
'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php', 'PhabricatorMacroTransactionType' => 'applications/macro/xaction/PhabricatorMacroTransactionType.php',
'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php', 'PhabricatorMacroViewController' => 'applications/macro/controller/PhabricatorMacroViewController.php',
'PhabricatorMailAdapter' => 'applications/metamta/adapter/PhabricatorMailAdapter.php',
'PhabricatorMailAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailAmazonSESAdapter.php',
'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php', 'PhabricatorMailAttachment' => 'applications/metamta/message/PhabricatorMailAttachment.php',
'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php', 'PhabricatorMailConfigTestCase' => 'applications/metamta/storage/__tests__/PhabricatorMailConfigTestCase.php',
'PhabricatorMailEmailEngine' => 'applications/metamta/engine/PhabricatorMailEmailEngine.php',
'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php', 'PhabricatorMailEmailHeraldField' => 'applications/metamta/herald/PhabricatorMailEmailHeraldField.php',
'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php', 'PhabricatorMailEmailHeraldFieldGroup' => 'applications/metamta/herald/PhabricatorMailEmailHeraldFieldGroup.php',
'PhabricatorMailEmailMessage' => 'applications/metamta/message/PhabricatorMailEmailMessage.php', 'PhabricatorMailEmailMessage' => 'applications/metamta/message/PhabricatorMailEmailMessage.php',
@ -3382,14 +3412,7 @@ phutil_register_library_map(array(
'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php', 'PhabricatorMailEngineExtension' => 'applications/metamta/engine/PhabricatorMailEngineExtension.php',
'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php', 'PhabricatorMailExternalMessage' => 'applications/metamta/message/PhabricatorMailExternalMessage.php',
'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php', 'PhabricatorMailHeader' => 'applications/metamta/message/PhabricatorMailHeader.php',
'PhabricatorMailImplementationAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAdapter.php', 'PhabricatorMailMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailMailgunAdapter.php',
'PhabricatorMailImplementationAmazonSESAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationAmazonSESAdapter.php',
'PhabricatorMailImplementationMailgunAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationMailgunAdapter.php',
'PhabricatorMailImplementationPHPMailerAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerAdapter.php',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPHPMailerLiteAdapter.php',
'PhabricatorMailImplementationPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationPostmarkAdapter.php',
'PhabricatorMailImplementationSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationSendGridAdapter.php',
'PhabricatorMailImplementationTestAdapter' => 'applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php',
'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php', 'PhabricatorMailManagementListInboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListInboundWorkflow.php',
'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php', 'PhabricatorMailManagementListOutboundWorkflow' => 'applications/metamta/management/PhabricatorMailManagementListOutboundWorkflow.php',
'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php', 'PhabricatorMailManagementReceiveTestWorkflow' => 'applications/metamta/management/PhabricatorMailManagementReceiveTestWorkflow.php',
@ -3400,19 +3423,28 @@ phutil_register_library_map(array(
'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php', 'PhabricatorMailManagementUnverifyWorkflow' => 'applications/metamta/management/PhabricatorMailManagementUnverifyWorkflow.php',
'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php', 'PhabricatorMailManagementVolumeWorkflow' => 'applications/metamta/management/PhabricatorMailManagementVolumeWorkflow.php',
'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php', 'PhabricatorMailManagementWorkflow' => 'applications/metamta/management/PhabricatorMailManagementWorkflow.php',
'PhabricatorMailMessageEngine' => 'applications/metamta/engine/PhabricatorMailMessageEngine.php',
'PhabricatorMailMustEncryptHeraldAction' => 'applications/metamta/herald/PhabricatorMailMustEncryptHeraldAction.php', 'PhabricatorMailMustEncryptHeraldAction' => 'applications/metamta/herald/PhabricatorMailMustEncryptHeraldAction.php',
'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php', 'PhabricatorMailOutboundMailHeraldAdapter' => 'applications/metamta/herald/PhabricatorMailOutboundMailHeraldAdapter.php',
'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php', 'PhabricatorMailOutboundRoutingHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingHeraldAction.php',
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php', 'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php', 'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php',
'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php', 'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php',
'PhabricatorMailPostmarkAdapter' => 'applications/metamta/adapter/PhabricatorMailPostmarkAdapter.php',
'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.php', 'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.php',
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php', 'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php', 'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php', 'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php', 'PhabricatorMailRoutingRule' => 'applications/metamta/constants/PhabricatorMailRoutingRule.php',
'PhabricatorMailSMSMessage' => 'applications/metamta/message/PhabricatorMailSMSMessage.php',
'PhabricatorMailSMTPAdapter' => 'applications/metamta/adapter/PhabricatorMailSMTPAdapter.php',
'PhabricatorMailSendGridAdapter' => 'applications/metamta/adapter/PhabricatorMailSendGridAdapter.php',
'PhabricatorMailSendmailAdapter' => 'applications/metamta/adapter/PhabricatorMailSendmailAdapter.php',
'PhabricatorMailSetupCheck' => 'applications/config/check/PhabricatorMailSetupCheck.php',
'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php', 'PhabricatorMailStamp' => 'applications/metamta/stamp/PhabricatorMailStamp.php',
'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php', 'PhabricatorMailTarget' => 'applications/metamta/replyhandler/PhabricatorMailTarget.php',
'PhabricatorMailTestAdapter' => 'applications/metamta/adapter/PhabricatorMailTestAdapter.php',
'PhabricatorMailTwilioAdapter' => 'applications/metamta/adapter/PhabricatorMailTwilioAdapter.php',
'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php', 'PhabricatorMailUtil' => 'applications/metamta/util/PhabricatorMailUtil.php',
'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php', 'PhabricatorMainMenuBarExtension' => 'view/page/menu/PhabricatorMainMenuBarExtension.php',
'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php', 'PhabricatorMainMenuSearchView' => 'view/page/menu/PhabricatorMainMenuSearchView.php',
@ -3747,7 +3779,6 @@ phutil_register_library_map(array(
'PhabricatorPaste' => 'applications/paste/storage/PhabricatorPaste.php', 'PhabricatorPaste' => 'applications/paste/storage/PhabricatorPaste.php',
'PhabricatorPasteApplication' => 'applications/paste/application/PhabricatorPasteApplication.php', 'PhabricatorPasteApplication' => 'applications/paste/application/PhabricatorPasteApplication.php',
'PhabricatorPasteArchiveController' => 'applications/paste/controller/PhabricatorPasteArchiveController.php', 'PhabricatorPasteArchiveController' => 'applications/paste/controller/PhabricatorPasteArchiveController.php',
'PhabricatorPasteConfigOptions' => 'applications/paste/config/PhabricatorPasteConfigOptions.php',
'PhabricatorPasteContentSearchEngineAttachment' => 'applications/paste/engineextension/PhabricatorPasteContentSearchEngineAttachment.php', 'PhabricatorPasteContentSearchEngineAttachment' => 'applications/paste/engineextension/PhabricatorPasteContentSearchEngineAttachment.php',
'PhabricatorPasteContentTransaction' => 'applications/paste/xaction/PhabricatorPasteContentTransaction.php', 'PhabricatorPasteContentTransaction' => 'applications/paste/xaction/PhabricatorPasteContentTransaction.php',
'PhabricatorPasteController' => 'applications/paste/controller/PhabricatorPasteController.php', 'PhabricatorPasteController' => 'applications/paste/controller/PhabricatorPasteController.php',
@ -3799,6 +3830,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php', 'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php', 'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php',
'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php', 'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php',
'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php', 'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php',
@ -3826,14 +3859,15 @@ phutil_register_library_map(array(
'PhabricatorPeopleUserFunctionDatasource' => 'applications/people/typeahead/PhabricatorPeopleUserFunctionDatasource.php', 'PhabricatorPeopleUserFunctionDatasource' => 'applications/people/typeahead/PhabricatorPeopleUserFunctionDatasource.php',
'PhabricatorPeopleUserPHIDType' => 'applications/people/phid/PhabricatorPeopleUserPHIDType.php', 'PhabricatorPeopleUserPHIDType' => 'applications/people/phid/PhabricatorPeopleUserPHIDType.php',
'PhabricatorPeopleWelcomeController' => 'applications/people/controller/PhabricatorPeopleWelcomeController.php', 'PhabricatorPeopleWelcomeController' => 'applications/people/controller/PhabricatorPeopleWelcomeController.php',
'PhabricatorPeopleWelcomeMailEngine' => 'applications/people/mail/PhabricatorPeopleWelcomeMailEngine.php',
'PhabricatorPhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorPhabricatorAuthProvider.php', 'PhabricatorPhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorPhabricatorAuthProvider.php',
'PhabricatorPhameApplication' => 'applications/phame/application/PhabricatorPhameApplication.php', 'PhabricatorPhameApplication' => 'applications/phame/application/PhabricatorPhameApplication.php',
'PhabricatorPhameBlogPHIDType' => 'applications/phame/phid/PhabricatorPhameBlogPHIDType.php', 'PhabricatorPhameBlogPHIDType' => 'applications/phame/phid/PhabricatorPhameBlogPHIDType.php',
'PhabricatorPhamePostPHIDType' => 'applications/phame/phid/PhabricatorPhamePostPHIDType.php', 'PhabricatorPhamePostPHIDType' => 'applications/phame/phid/PhabricatorPhamePostPHIDType.php',
'PhabricatorPhluxApplication' => 'applications/phlux/application/PhabricatorPhluxApplication.php', 'PhabricatorPhluxApplication' => 'applications/phlux/application/PhabricatorPhluxApplication.php',
'PhabricatorPholioApplication' => 'applications/pholio/application/PhabricatorPholioApplication.php', 'PhabricatorPholioApplication' => 'applications/pholio/application/PhabricatorPholioApplication.php',
'PhabricatorPholioConfigOptions' => 'applications/pholio/config/PhabricatorPholioConfigOptions.php',
'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php', 'PhabricatorPholioMockTestDataGenerator' => 'applications/pholio/lipsum/PhabricatorPholioMockTestDataGenerator.php',
'PhabricatorPhoneNumber' => 'applications/metamta/message/PhabricatorPhoneNumber.php',
'PhabricatorPhortuneApplication' => 'applications/phortune/application/PhabricatorPhortuneApplication.php', 'PhabricatorPhortuneApplication' => 'applications/phortune/application/PhabricatorPhortuneApplication.php',
'PhabricatorPhortuneContentSource' => 'applications/phortune/contentsource/PhabricatorPhortuneContentSource.php', 'PhabricatorPhortuneContentSource' => 'applications/phortune/contentsource/PhabricatorPhortuneContentSource.php',
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php', 'PhabricatorPhortuneManagementInvoiceWorkflow' => 'applications/phortune/management/PhabricatorPhortuneManagementInvoiceWorkflow.php',
@ -3842,7 +3876,6 @@ phutil_register_library_map(array(
'PhabricatorPhragmentApplication' => 'applications/phragment/application/PhabricatorPhragmentApplication.php', 'PhabricatorPhragmentApplication' => 'applications/phragment/application/PhabricatorPhragmentApplication.php',
'PhabricatorPhrequentApplication' => 'applications/phrequent/application/PhabricatorPhrequentApplication.php', 'PhabricatorPhrequentApplication' => 'applications/phrequent/application/PhabricatorPhrequentApplication.php',
'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php', 'PhabricatorPhrictionApplication' => 'applications/phriction/application/PhabricatorPhrictionApplication.php',
'PhabricatorPhrictionConfigOptions' => 'applications/phriction/config/PhabricatorPhrictionConfigOptions.php',
'PhabricatorPhurlApplication' => 'applications/phurl/application/PhabricatorPhurlApplication.php', 'PhabricatorPhurlApplication' => 'applications/phurl/application/PhabricatorPhurlApplication.php',
'PhabricatorPhurlConfigOptions' => 'applications/config/option/PhabricatorPhurlConfigOptions.php', 'PhabricatorPhurlConfigOptions' => 'applications/config/option/PhabricatorPhurlConfigOptions.php',
'PhabricatorPhurlController' => 'applications/phurl/controller/PhabricatorPhurlController.php', 'PhabricatorPhurlController' => 'applications/phurl/controller/PhabricatorPhurlController.php',
@ -4885,7 +4918,9 @@ phutil_register_library_map(array(
'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php', 'PholioUploadedImageView' => 'applications/pholio/view/PholioUploadedImageView.php',
'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php', 'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php',
'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php', 'PhortuneAccountAddManagerController' => 'applications/phortune/controller/account/PhortuneAccountAddManagerController.php',
'PhortuneAccountBillingAddressTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingAddressTransaction.php',
'PhortuneAccountBillingController' => 'applications/phortune/controller/account/PhortuneAccountBillingController.php', 'PhortuneAccountBillingController' => 'applications/phortune/controller/account/PhortuneAccountBillingController.php',
'PhortuneAccountBillingNameTransaction' => 'applications/phortune/xaction/PhortuneAccountBillingNameTransaction.php',
'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php', 'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php',
'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php', 'PhortuneAccountController' => 'applications/phortune/controller/account/PhortuneAccountController.php',
'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php', 'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php',
@ -5721,7 +5756,6 @@ phutil_register_library_map(array(
'ConduitWildParameterType' => 'ConduitParameterType', 'ConduitWildParameterType' => 'ConduitParameterType',
'ConpherenceColumnViewController' => 'ConpherenceController', 'ConpherenceColumnViewController' => 'ConpherenceController',
'ConpherenceConduitAPIMethod' => 'ConduitAPIMethod', 'ConpherenceConduitAPIMethod' => 'ConduitAPIMethod',
'ConpherenceConfigOptions' => 'PhabricatorApplicationConfigOptions',
'ConpherenceConstants' => 'Phobject', 'ConpherenceConstants' => 'Phobject',
'ConpherenceController' => 'PhabricatorController', 'ConpherenceController' => 'PhabricatorController',
'ConpherenceCreateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod', 'ConpherenceCreateThreadConduitAPIMethod' => 'ConpherenceConduitAPIMethod',
@ -7834,6 +7868,7 @@ phutil_register_library_map(array(
'PhabricatorAuthAccountView' => 'AphrontView', 'PhabricatorAuthAccountView' => 'AphrontView',
'PhabricatorAuthApplication' => 'PhabricatorApplication', 'PhabricatorAuthApplication' => 'PhabricatorApplication',
'PhabricatorAuthAuthFactorPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthAuthFactorPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthAuthFactorProviderPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthAuthProviderPHIDType' => 'PhabricatorPHIDType', 'PhabricatorAuthAuthProviderPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthCSRFEngine' => 'Phobject', 'PhabricatorAuthCSRFEngine' => 'Phobject',
'PhabricatorAuthChallenge' => array( 'PhabricatorAuthChallenge' => array(
@ -7854,6 +7889,23 @@ phutil_register_library_map(array(
'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthEditController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthFactor' => 'Phobject', 'PhabricatorAuthFactor' => 'Phobject',
'PhabricatorAuthFactorConfig' => 'PhabricatorAuthDAO', 'PhabricatorAuthFactorConfig' => 'PhabricatorAuthDAO',
'PhabricatorAuthFactorProvider' => array(
'PhabricatorAuthDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface',
'PhabricatorExtendedPolicyInterface',
),
'PhabricatorAuthFactorProviderController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthFactorProviderEditController' => 'PhabricatorAuthFactorProviderController',
'PhabricatorAuthFactorProviderEditEngine' => 'PhabricatorEditEngine',
'PhabricatorAuthFactorProviderEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthFactorProviderListController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthFactorProviderNameTransaction' => 'PhabricatorAuthFactorProviderTransactionType',
'PhabricatorAuthFactorProviderQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthFactorProviderTransaction' => 'PhabricatorModularTransaction',
'PhabricatorAuthFactorProviderTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthFactorProviderTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorAuthFactorProviderViewController' => 'PhabricatorAuthFactorProviderController',
'PhabricatorAuthFactorResult' => 'Phobject', 'PhabricatorAuthFactorResult' => 'Phobject',
'PhabricatorAuthFactorTestCase' => 'PhabricatorTestCase', 'PhabricatorAuthFactorTestCase' => 'PhabricatorTestCase',
'PhabricatorAuthFinishController' => 'PhabricatorAuthController', 'PhabricatorAuthFinishController' => 'PhabricatorAuthController',
@ -7884,6 +7936,7 @@ phutil_register_library_map(array(
'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthListController' => 'PhabricatorAuthProviderConfigController',
'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 'PhabricatorAuthLoginController' => 'PhabricatorAuthController',
'PhabricatorAuthLoginHandler' => 'Phobject', 'PhabricatorAuthLoginHandler' => 'Phobject',
'PhabricatorAuthLoginMessageType' => 'PhabricatorAuthMessageType',
'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthLogoutConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod',
'PhabricatorAuthMFAEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorAuthMFAEditEngineExtension' => 'PhabricatorEditEngineExtension',
'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', 'PhabricatorAuthMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
@ -7899,6 +7952,25 @@ phutil_register_library_map(array(
'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementUntrustOAuthClientWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow', 'PhabricatorAuthManagementVerifyWorkflow' => 'PhabricatorAuthManagementWorkflow',
'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorAuthManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorAuthMessage' => array(
'PhabricatorAuthDAO',
'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
),
'PhabricatorAuthMessageController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthMessageEditController' => 'PhabricatorAuthMessageController',
'PhabricatorAuthMessageEditEngine' => 'PhabricatorEditEngine',
'PhabricatorAuthMessageEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthMessageListController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthMessagePHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthMessageQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthMessageTextTransaction' => 'PhabricatorAuthMessageTransactionType',
'PhabricatorAuthMessageTransaction' => 'PhabricatorModularTransaction',
'PhabricatorAuthMessageTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthMessageTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorAuthMessageType' => 'Phobject',
'PhabricatorAuthMessageViewController' => 'PhabricatorAuthMessageController',
'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsApprovalController' => 'PhabricatorAuthController',
'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController', 'PhabricatorAuthNeedsMultiFactorController' => 'PhabricatorAuthController',
'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController', 'PhabricatorAuthNewController' => 'PhabricatorAuthProviderConfigController',
@ -7930,11 +8002,12 @@ phutil_register_library_map(array(
'PhabricatorApplicationTransactionInterface', 'PhabricatorApplicationTransactionInterface',
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
), ),
'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthController', 'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthProviderController',
'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', 'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorAuthProviderConfigQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction', 'PhabricatorAuthProviderConfigTransaction' => 'PhabricatorApplicationTransaction',
'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorAuthProviderConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthProviderController' => 'PhabricatorAuthController',
'PhabricatorAuthProvidersGuidanceContext' => 'PhabricatorGuidanceContext', 'PhabricatorAuthProvidersGuidanceContext' => 'PhabricatorGuidanceContext',
'PhabricatorAuthProvidersGuidanceEngineExtension' => 'PhabricatorGuidanceEngineExtension', 'PhabricatorAuthProvidersGuidanceEngineExtension' => 'PhabricatorGuidanceEngineExtension',
'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod', 'PhabricatorAuthQueryPublicKeysConduitAPIMethod' => 'PhabricatorAuthConduitAPIMethod',
@ -7993,6 +8066,7 @@ phutil_register_library_map(array(
'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction', 'PhabricatorAuthTryFactorAction' => 'PhabricatorSystemAction',
'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController', 'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController',
'PhabricatorAuthValidateController' => 'PhabricatorAuthController', 'PhabricatorAuthValidateController' => 'PhabricatorAuthController',
'PhabricatorAuthWelcomeMailMessageType' => 'PhabricatorAuthMessageType',
'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorAuthenticationConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorAutoEventListener' => 'PhabricatorEventListener', 'PhabricatorAutoEventListener' => 'PhabricatorEventListener',
'PhabricatorBadgesApplication' => 'PhabricatorApplication', 'PhabricatorBadgesApplication' => 'PhabricatorApplication',
@ -9131,7 +9205,6 @@ phutil_register_library_map(array(
'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider', 'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider',
'PhabricatorLabelProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorLabelProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorLegalpadApplication' => 'PhabricatorApplication', 'PhabricatorLegalpadApplication' => 'PhabricatorApplication',
'PhabricatorLegalpadConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType', 'PhabricatorLegalpadDocumentPHIDType' => 'PhabricatorPHIDType',
'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorLegalpadSignaturePolicyRule' => 'PhabricatorPolicyRule',
'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase', 'PhabricatorLibraryTestCase' => 'PhutilLibraryTestCase',
@ -9160,7 +9233,6 @@ phutil_register_library_map(array(
'PhabricatorMacroAudioBehaviorTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroAudioBehaviorTransaction' => 'PhabricatorMacroTransactionType',
'PhabricatorMacroAudioController' => 'PhabricatorMacroController', 'PhabricatorMacroAudioController' => 'PhabricatorMacroController',
'PhabricatorMacroAudioTransaction' => 'PhabricatorMacroTransactionType', 'PhabricatorMacroAudioTransaction' => 'PhabricatorMacroTransactionType',
'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMacroController' => 'PhabricatorController', 'PhabricatorMacroController' => 'PhabricatorController',
'PhabricatorMacroDatasource' => 'PhabricatorTypeaheadDatasource', 'PhabricatorMacroDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorMacroDisableController' => 'PhabricatorMacroController', 'PhabricatorMacroDisableController' => 'PhabricatorMacroController',
@ -9185,8 +9257,11 @@ phutil_register_library_map(array(
'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery', 'PhabricatorMacroTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType', 'PhabricatorMacroTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorMacroViewController' => 'PhabricatorMacroController', 'PhabricatorMacroViewController' => 'PhabricatorMacroController',
'PhabricatorMailAdapter' => 'Phobject',
'PhabricatorMailAmazonSESAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailAttachment' => 'Phobject', 'PhabricatorMailAttachment' => 'Phobject',
'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase', 'PhabricatorMailConfigTestCase' => 'PhabricatorTestCase',
'PhabricatorMailEmailEngine' => 'PhabricatorMailMessageEngine',
'PhabricatorMailEmailHeraldField' => 'HeraldField', 'PhabricatorMailEmailHeraldField' => 'HeraldField',
'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup', 'PhabricatorMailEmailHeraldFieldGroup' => 'HeraldFieldGroup',
'PhabricatorMailEmailMessage' => 'PhabricatorMailExternalMessage', 'PhabricatorMailEmailMessage' => 'PhabricatorMailExternalMessage',
@ -9194,14 +9269,7 @@ phutil_register_library_map(array(
'PhabricatorMailEngineExtension' => 'Phobject', 'PhabricatorMailEngineExtension' => 'Phobject',
'PhabricatorMailExternalMessage' => 'Phobject', 'PhabricatorMailExternalMessage' => 'Phobject',
'PhabricatorMailHeader' => 'Phobject', 'PhabricatorMailHeader' => 'Phobject',
'PhabricatorMailImplementationAdapter' => 'Phobject', 'PhabricatorMailMailgunAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailImplementationAmazonSESAdapter' => 'PhabricatorMailImplementationPHPMailerLiteAdapter',
'PhabricatorMailImplementationMailgunAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationPHPMailerAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationPHPMailerLiteAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationPostmarkAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationSendGridAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailImplementationTestAdapter' => 'PhabricatorMailImplementationAdapter',
'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementListInboundWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementListOutboundWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementReceiveTestWorkflow' => 'PhabricatorMailManagementWorkflow',
@ -9212,19 +9280,28 @@ phutil_register_library_map(array(
'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementUnverifyWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow', 'PhabricatorMailManagementVolumeWorkflow' => 'PhabricatorMailManagementWorkflow',
'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorMailManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorMailMessageEngine' => 'Phobject',
'PhabricatorMailMustEncryptHeraldAction' => 'HeraldAction', 'PhabricatorMailMustEncryptHeraldAction' => 'HeraldAction',
'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter', 'PhabricatorMailOutboundMailHeraldAdapter' => 'HeraldAdapter',
'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction', 'PhabricatorMailOutboundRoutingHeraldAction' => 'HeraldAction',
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction', 'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
'PhabricatorMailOutboundStatus' => 'Phobject', 'PhabricatorMailOutboundStatus' => 'Phobject',
'PhabricatorMailPostmarkAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', 'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'PhabricatorMailReceiver' => 'Phobject', 'PhabricatorMailReceiver' => 'Phobject',
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase', 'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorMailReplyHandler' => 'Phobject', 'PhabricatorMailReplyHandler' => 'Phobject',
'PhabricatorMailRoutingRule' => 'Phobject', 'PhabricatorMailRoutingRule' => 'Phobject',
'PhabricatorMailSMSMessage' => 'PhabricatorMailExternalMessage',
'PhabricatorMailSMTPAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailSendGridAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailSendmailAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailSetupCheck' => 'PhabricatorSetupCheck',
'PhabricatorMailStamp' => 'Phobject', 'PhabricatorMailStamp' => 'Phobject',
'PhabricatorMailTarget' => 'Phobject', 'PhabricatorMailTarget' => 'Phobject',
'PhabricatorMailTestAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailTwilioAdapter' => 'PhabricatorMailAdapter',
'PhabricatorMailUtil' => 'Phobject', 'PhabricatorMailUtil' => 'Phobject',
'PhabricatorMainMenuBarExtension' => 'Phobject', 'PhabricatorMainMenuBarExtension' => 'Phobject',
'PhabricatorMainMenuSearchView' => 'AphrontView', 'PhabricatorMainMenuSearchView' => 'AphrontView',
@ -9642,7 +9719,6 @@ phutil_register_library_map(array(
), ),
'PhabricatorPasteApplication' => 'PhabricatorApplication', 'PhabricatorPasteApplication' => 'PhabricatorApplication',
'PhabricatorPasteArchiveController' => 'PhabricatorPasteController', 'PhabricatorPasteArchiveController' => 'PhabricatorPasteController',
'PhabricatorPasteConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPasteContentSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorPasteContentSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
'PhabricatorPasteContentTransaction' => 'PhabricatorPasteTransactionType', 'PhabricatorPasteContentTransaction' => 'PhabricatorPasteTransactionType',
'PhabricatorPasteController' => 'PhabricatorController', 'PhabricatorPasteController' => 'PhabricatorController',
@ -9694,6 +9770,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleMailEngine' => 'Phobject',
'PhabricatorPeopleMailEngineException' => 'Exception',
'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow', 'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorPeopleNewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleNewController' => 'PhabricatorPeopleController',
@ -9721,14 +9799,15 @@ phutil_register_library_map(array(
'PhabricatorPeopleUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', 'PhabricatorPeopleUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorPeopleUserPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPeopleUserPHIDType' => 'PhabricatorPHIDType',
'PhabricatorPeopleWelcomeController' => 'PhabricatorPeopleController', 'PhabricatorPeopleWelcomeController' => 'PhabricatorPeopleController',
'PhabricatorPeopleWelcomeMailEngine' => 'PhabricatorPeopleMailEngine',
'PhabricatorPhabricatorAuthProvider' => 'PhabricatorOAuth2AuthProvider', 'PhabricatorPhabricatorAuthProvider' => 'PhabricatorOAuth2AuthProvider',
'PhabricatorPhameApplication' => 'PhabricatorApplication', 'PhabricatorPhameApplication' => 'PhabricatorApplication',
'PhabricatorPhameBlogPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhameBlogPHIDType' => 'PhabricatorPHIDType',
'PhabricatorPhamePostPHIDType' => 'PhabricatorPHIDType', 'PhabricatorPhamePostPHIDType' => 'PhabricatorPHIDType',
'PhabricatorPhluxApplication' => 'PhabricatorApplication', 'PhabricatorPhluxApplication' => 'PhabricatorApplication',
'PhabricatorPholioApplication' => 'PhabricatorApplication', 'PhabricatorPholioApplication' => 'PhabricatorApplication',
'PhabricatorPholioConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator', 'PhabricatorPholioMockTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPhoneNumber' => 'Phobject',
'PhabricatorPhortuneApplication' => 'PhabricatorApplication', 'PhabricatorPhortuneApplication' => 'PhabricatorApplication',
'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource', 'PhabricatorPhortuneContentSource' => 'PhabricatorContentSource',
'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow', 'PhabricatorPhortuneManagementInvoiceWorkflow' => 'PhabricatorPhortuneManagementWorkflow',
@ -9737,7 +9816,6 @@ phutil_register_library_map(array(
'PhabricatorPhragmentApplication' => 'PhabricatorApplication', 'PhabricatorPhragmentApplication' => 'PhabricatorApplication',
'PhabricatorPhrequentApplication' => 'PhabricatorApplication', 'PhabricatorPhrequentApplication' => 'PhabricatorApplication',
'PhabricatorPhrictionApplication' => 'PhabricatorApplication', 'PhabricatorPhrictionApplication' => 'PhabricatorApplication',
'PhabricatorPhrictionConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhurlApplication' => 'PhabricatorApplication', 'PhabricatorPhurlApplication' => 'PhabricatorApplication',
'PhabricatorPhurlConfigOptions' => 'PhabricatorApplicationConfigOptions', 'PhabricatorPhurlConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorPhurlController' => 'PhabricatorController', 'PhabricatorPhurlController' => 'PhabricatorController',
@ -11022,7 +11100,9 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface', 'PhabricatorPolicyInterface',
), ),
'PhortuneAccountAddManagerController' => 'PhortuneController', 'PhortuneAccountAddManagerController' => 'PhortuneController',
'PhortuneAccountBillingAddressTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountBillingController' => 'PhortuneAccountProfileController', 'PhortuneAccountBillingController' => 'PhortuneAccountProfileController',
'PhortuneAccountBillingNameTransaction' => 'PhortuneAccountTransactionType',
'PhortuneAccountChargeListController' => 'PhortuneController', 'PhortuneAccountChargeListController' => 'PhortuneController',
'PhortuneAccountController' => 'PhortuneController', 'PhortuneAccountController' => 'PhortuneController',
'PhortuneAccountEditController' => 'PhortuneController', 'PhortuneAccountEditController' => 'PhortuneController',

View file

@ -437,7 +437,7 @@ final class PhabricatorAuditEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.diffusion.subject-prefix'); return pht('[Diffusion]');
} }
protected function getMailThreadID(PhabricatorLiskDAO $object) { protected function getMailThreadID(PhabricatorLiskDAO $object) {

View file

@ -12,7 +12,7 @@ final class PhabricatorAuditMailReceiver extends PhabricatorObjectMailReceiver {
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)preg_replace('/^COMMIT/', '', $pattern); $id = (int)preg_replace('/^COMMIT/i', '', $pattern);
return id(new DiffusionCommitQuery()) return id(new DiffusionCommitQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -85,6 +85,25 @@ final class PhabricatorAuthApplication extends PhabricatorApplication {
'view/(?P<id>\d+)/' => 'PhabricatorAuthSSHKeyViewController', 'view/(?P<id>\d+)/' => 'PhabricatorAuthSSHKeyViewController',
), ),
'password/' => 'PhabricatorAuthSetPasswordController', 'password/' => 'PhabricatorAuthSetPasswordController',
'mfa/' => array(
$this->getQueryRoutePattern() =>
'PhabricatorAuthFactorProviderListController',
$this->getEditRoutePattern('edit/') =>
'PhabricatorAuthFactorProviderEditController',
'(?P<id>[1-9]\d*)/' =>
'PhabricatorAuthFactorProviderViewController',
),
'message/' => array(
$this->getQueryRoutePattern() =>
'PhabricatorAuthMessageListController',
$this->getEditRoutePattern('edit/') =>
'PhabricatorAuthMessageEditController',
'(?P<id>[1-9]\d*)/' =>
'PhabricatorAuthMessageViewController',
),
), ),
'/oauth/(?P<provider>\w+)/login/' '/oauth/(?P<provider>\w+)/login/'

View file

@ -17,6 +17,7 @@ final class PhabricatorAuthLoginController
if ($parameter_name == 'code') { if ($parameter_name == 'code') {
return true; return true;
} }
return parent::shouldAllowRestrictedParameter($parameter_name); return parent::shouldAllowRestrictedParameter($parameter_name);
} }

View file

@ -194,6 +194,8 @@ final class PhabricatorAuthStartController
$invite_message = $this->renderInviteHeader($invite); $invite_message = $this->renderInviteHeader($invite);
} }
$custom_message = $this->newCustomStartMessage();
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Login')); $crumbs->addTextCrumb(pht('Login'));
$crumbs->setBorder(true); $crumbs->setBorder(true);
@ -202,6 +204,7 @@ final class PhabricatorAuthStartController
$view = array( $view = array(
$header, $header,
$invite_message, $invite_message,
$custom_message,
$out, $out,
); );
@ -305,4 +308,25 @@ final class PhabricatorAuthStartController
->setURI($auto_uri); ->setURI($auto_uri);
} }
private function newCustomStartMessage() {
$viewer = $this->getViewer();
$text = PhabricatorAuthMessage::loadMessageText(
$viewer,
PhabricatorAuthLoginMessageType::MESSAGEKEY);
if (!strlen($text)) {
return null;
}
$remarkup_view = new PHUIRemarkupView($viewer, $text);
return phutil_tag(
'div',
array(
'class' => 'auth-custom-message',
),
$remarkup_view);
}
} }

View file

@ -91,7 +91,7 @@ final class PhabricatorAuthListController
pht('Add Authentication Provider')))); pht('Add Authentication Provider'))));
$crumbs = $this->buildApplicationCrumbs(); $crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Auth Providers')); $crumbs->addTextCrumb(pht('Login and Registration'));
$crumbs->setBorder(true); $crumbs->setBorder(true);
$guidance_context = new PhabricatorAuthProvidersGuidanceContext(); $guidance_context = new PhabricatorAuthProvidersGuidanceContext();
@ -115,7 +115,7 @@ final class PhabricatorAuthListController
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($list); ->appendChild($list);
$title = pht('Auth Providers'); $title = pht('Login and Registration Providers');
$header = id(new PHUIHeaderView()) $header = id(new PHUIHeaderView())
->setHeader($title) ->setHeader($title)
->setHeaderIcon('fa-key') ->setHeaderIcon('fa-key')
@ -128,10 +128,15 @@ final class PhabricatorAuthListController
$list, $list,
)); ));
return $this->newPage() $nav = $this->newNavigation()
->setTitle($title)
->setCrumbs($crumbs) ->setCrumbs($crumbs)
->appendChild($view); ->appendChild($view);
$nav->selectFilter('login');
return $this->newPage()
->setTitle($title)
->appendChild($nav);
} }
} }

View file

@ -1,32 +1,4 @@
<?php <?php
abstract class PhabricatorAuthProviderConfigController abstract class PhabricatorAuthProviderConfigController
extends PhabricatorAuthController { extends PhabricatorAuthProviderController {}
protected function buildSideNavView($for_app = false) {
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
if ($for_app) {
$nav->addLabel(pht('Create'));
$nav->addFilter('',
pht('Add Authentication Provider'),
$this->getApplicationURI('/config/new/'));
}
return $nav;
}
public function buildApplicationMenu() {
return $this->buildSideNavView($for_app = true)->getMenu();
}
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
$can_create = $this->hasApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
return $crumbs;
}
}

View file

@ -0,0 +1,57 @@
<?php
abstract class PhabricatorAuthProviderController
extends PhabricatorAuthController {
protected function newNavigation() {
$viewer = $this->getViewer();
$nav = id(new AphrontSideNavFilterView())
->setBaseURI(new PhutilURI($this->getApplicationURI()))
->setViewer($viewer);
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Authentication'))
->setType(PHUIListItemView::TYPE_LABEL));
$nav->addMenuItem(
id(new PHUIListItemView())
->setKey('login')
->setName(pht('Login and Registration'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref($this->getApplicationURI('/'))
->setIcon('fa-key'));
$nav->addMenuItem(
id(new PHUIListItemView())
->setKey('mfa')
->setName(pht('Multi-Factor'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref($this->getApplicationURI('mfa/'))
->setIcon('fa-mobile'));
$nav->addMenuItem(
id(new PHUIListItemView())
->setName(pht('Onboarding'))
->setType(PHUIListItemView::TYPE_LABEL));
$nav->addMenuItem(
id(new PHUIListItemView())
->setKey('message')
->setName(pht('Customize Messages'))
->setType(PHUIListItemView::TYPE_LINK)
->setHref($this->getApplicationURI('message/'))
->setIcon('fa-commenting-o'));
$nav->selectFilter(null);
return $nav;
}
public function buildApplicationMenu() {
return $this->newNavigation()->getMenu();
}
}

View file

@ -0,0 +1,11 @@
<?php
abstract class PhabricatorAuthMessageController
extends PhabricatorAuthProviderController {
protected function buildApplicationCrumbs() {
return parent::buildApplicationCrumbs()
->addTextCrumb(pht('Messages'), $this->getApplicationURI('message/'));
}
}

View file

@ -0,0 +1,31 @@
<?php
final class PhabricatorAuthMessageEditController
extends PhabricatorAuthMessageController {
public function handleRequest(AphrontRequest $request) {
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$engine = id(new PhabricatorAuthMessageEditEngine())
->setController($this);
$id = $request->getURIData('id');
if (!$id) {
$message_key = $request->getStr('messageKey');
$message_types = PhabricatorAuthMessageType::getAllMessageTypes();
$message_type = idx($message_types, $message_key);
if (!$message_type) {
return new Aphront404Response();
}
$engine
->addContextParameter('messageKey', $message_key)
->setMessageType($message_type);
}
return $engine->buildResponse();
}
}

View file

@ -0,0 +1,77 @@
<?php
final class PhabricatorAuthMessageListController
extends PhabricatorAuthProviderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$can_manage = $this->hasApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$types = PhabricatorAuthMessageType::getAllMessageTypes();
$messages = id(new PhabricatorAuthMessageQuery())
->setViewer($viewer)
->execute();
$messages = mpull($messages, null, 'getMessageKey');
$list = new PHUIObjectItemListView();
foreach ($types as $type) {
$message = idx($messages, $type->getMessageTypeKey());
if ($message) {
$href = $message->getURI();
$name = $message->getMessageTypeDisplayName();
} else {
$href = '/auth/message/edit/?messageKey='.$type->getMessageTypeKey();
$name = $type->getDisplayName();
}
$item = id(new PHUIObjectItemView())
->setHeader($name)
->setHref($href)
->addAttribute($type->getShortDescription());
if ($message) {
$item->addIcon('fa-circle', pht('Customized'));
} else {
$item->addIcon('fa-circle-o grey', pht('Default'));
}
$list->addItem($item);
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb(pht('Messages'))
->setBorder(true);
$list->setFlush(true);
$list = id(new PHUIObjectBoxView())
->setHeaderText(pht('Auth Messages'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($list);
$title = pht('Auth Messages');
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon('fa-commenting-o');
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(
array(
$list,
));
$nav = $this->newNavigation()
->setCrumbs($crumbs)
->appendChild($view);
$nav->selectFilter('message');
return $this->newPage()
->setTitle($title)
->appendChild($nav);
}
}

View file

@ -0,0 +1,104 @@
<?php
final class PhabricatorAuthMessageViewController
extends PhabricatorAuthMessageController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$message = id(new PhabricatorAuthMessageQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$message) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($message->getObjectName())
->setBorder(true);
$header = $this->buildHeaderView($message);
$properties = $this->buildPropertiesView($message);
$curtain = $this->buildCurtain($message);
$timeline = $this->buildTransactionTimeline(
$message,
new PhabricatorAuthMessageTransactionQuery());
$timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(
array(
$timeline,
))
->addPropertySection(pht('Details'), $properties);
return $this->newPage()
->setTitle($message->getMessageTypeDisplayName())
->setCrumbs($crumbs)
->setPageObjectPHIDs(
array(
$message->getPHID(),
))
->appendChild($view);
}
private function buildHeaderView(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$view = id(new PHUIHeaderView())
->setViewer($viewer)
->setHeader($message->getMessageTypeDisplayName());
return $view;
}
private function buildPropertiesView(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setViewer($viewer);
$view->addProperty(
pht('Description'),
$message->getMessageType()->getShortDescription());
$view->addSectionHeader(
pht('Message Preview'),
PHUIPropertyListView::ICON_SUMMARY);
$view->addTextContent(
new PHUIRemarkupView($viewer, $message->getMessageText()));
return $view;
}
private function buildCurtain(PhabricatorAuthMessage $message) {
$viewer = $this->getViewer();
$id = $message->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$message,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($message);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Message'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("message/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $curtain;
}
}

View file

@ -0,0 +1,11 @@
<?php
abstract class PhabricatorAuthFactorProviderController
extends PhabricatorAuthProviderController {
protected function buildApplicationCrumbs() {
return parent::buildApplicationCrumbs()
->addTextCrumb(pht('Multi-Factor'), $this->getApplicationURI('mfa/'));
}
}

View file

@ -0,0 +1,65 @@
<?php
final class PhabricatorAuthFactorProviderEditController
extends PhabricatorAuthFactorProviderController {
public function handleRequest(AphrontRequest $request) {
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$engine = id(new PhabricatorAuthFactorProviderEditEngine())
->setController($this);
$id = $request->getURIData('id');
if (!$id) {
$factor_key = $request->getStr('providerFactorKey');
$map = PhabricatorAuthFactor::getAllFactors();
$factor = idx($map, $factor_key);
if (!$factor) {
return $this->buildFactorSelectionResponse();
}
$engine
->addContextParameter('providerFactorKey', $factor_key)
->setProviderFactor($factor);
}
return $engine->buildResponse();
}
private function buildFactorSelectionResponse() {
$request = $this->getRequest();
$viewer = $this->getViewer();
$cancel_uri = $this->getApplicationURI('mfa/');
$factors = PhabricatorAuthFactor::getAllFactors();
$menu = id(new PHUIObjectItemListView())
->setUser($viewer)
->setBig(true)
->setFlush(true);
foreach ($factors as $factor_key => $factor) {
$factor_uri = id(new PhutilURI('/mfa/edit/'))
->setQueryParam('providerFactorKey', $factor_key);
$factor_uri = $this->getApplicationURI($factor_uri);
$item = id(new PHUIObjectItemView())
->setHeader($factor->getFactorName())
->setHref($factor_uri)
->setClickable(true)
->setImageIcon($factor->newIconView())
->addAttribute($factor->getFactorCreateHelp());
$menu->addItem($item);
}
return $this->newDialog()
->setTitle(pht('Choose Provider Type'))
->appendChild($menu)
->addCancelButton($cancel_uri);
}
}

View file

@ -0,0 +1,72 @@
<?php
final class PhabricatorAuthFactorProviderListController
extends PhabricatorAuthProviderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$can_manage = $this->hasApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$providers = id(new PhabricatorAuthFactorProviderQuery())
->setViewer($viewer)
->execute();
$list = new PHUIObjectItemListView();
foreach ($providers as $provider) {
$item = id(new PHUIObjectItemView())
->setObjectName($provider->getObjectName())
->setHeader($provider->getDisplayName())
->setHref($provider->getURI());
$list->addItem($item);
}
$list->setNoDataString(
pht('You have not configured any multi-factor providers yet.'));
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb(pht('Multi-Factor'))
->setBorder(true);
$button = id(new PHUIButtonView())
->setTag('a')
->setButtonType(PHUIButtonView::BUTTONTYPE_SIMPLE)
->setHref($this->getApplicationURI('mfa/edit/'))
->setIcon('fa-plus')
->setDisabled(!$can_manage)
->setWorkflow(true)
->setText(pht('Add MFA Provider'));
$list->setFlush(true);
$list = id(new PHUIObjectBoxView())
->setHeaderText(pht('MFA Providers'))
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
->appendChild($list);
$title = pht('MFA Providers');
$header = id(new PHUIHeaderView())
->setHeader($title)
->setHeaderIcon('fa-mobile')
->addActionLink($button);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setFooter(
array(
$list,
));
$nav = $this->newNavigation()
->setCrumbs($crumbs)
->appendChild($view);
$nav->selectFilter('mfa');
return $this->newPage()
->setTitle($title)
->appendChild($nav);
}
}

View file

@ -0,0 +1,100 @@
<?php
final class PhabricatorAuthFactorProviderViewController
extends PhabricatorAuthFactorProviderController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$this->requireApplicationCapability(
AuthManageProvidersCapability::CAPABILITY);
$provider = id(new PhabricatorAuthFactorProviderQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->executeOne();
if (!$provider) {
return new Aphront404Response();
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($provider->getObjectName())
->setBorder(true);
$header = $this->buildHeaderView($provider);
$properties = $this->buildPropertiesView($provider);
$curtain = $this->buildCurtain($provider);
$timeline = $this->buildTransactionTimeline(
$provider,
new PhabricatorAuthFactorProviderTransactionQuery());
$timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
->setCurtain($curtain)
->setMainColumn(
array(
$timeline,
))
->addPropertySection(pht('Details'), $properties);
return $this->newPage()
->setTitle($provider->getDisplayName())
->setCrumbs($crumbs)
->setPageObjectPHIDs(
array(
$provider->getPHID(),
))
->appendChild($view);
}
private function buildHeaderView(PhabricatorAuthFactorProvider $provider) {
$viewer = $this->getViewer();
$view = id(new PHUIHeaderView())
->setViewer($viewer)
->setHeader($provider->getDisplayName())
->setPolicyObject($provider);
return $view;
}
private function buildPropertiesView(
PhabricatorAuthFactorProvider $provider) {
$viewer = $this->getViewer();
$view = id(new PHUIPropertyListView())
->setViewer($viewer);
$view->addProperty(
pht('Factor Type'),
$provider->getFactor()->getFactorName());
return $view;
}
private function buildCurtain(PhabricatorAuthFactorProvider $provider) {
$viewer = $this->getViewer();
$id = $provider->getID();
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$provider,
PhabricatorPolicyCapability::CAN_EDIT);
$curtain = $this->newCurtainView($provider);
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit MFA Provider'))
->setIcon('fa-pencil')
->setHref($this->getApplicationURI("mfa/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow(!$can_edit));
return $curtain;
}
}

View file

@ -0,0 +1,115 @@
<?php
final class PhabricatorAuthFactorProviderEditEngine
extends PhabricatorEditEngine {
private $providerFactor;
const ENGINECONST = 'auth.factor.provider';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('MFA Providers');
}
public function getSummaryHeader() {
return pht('Edit MFA Providers');
}
public function getSummaryText() {
return pht('This engine is used to edit MFA providers.');
}
public function getEngineApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function setProviderFactor(PhabricatorAuthFactor $factor) {
$this->providerFactor = $factor;
return $this;
}
public function getProviderFactor() {
return $this->providerFactor;
}
protected function newEditableObject() {
$factor = $this->getProviderFactor();
if ($factor) {
$provider = PhabricatorAuthFactorProvider::initializeNewProvider($factor);
} else {
$provider = new PhabricatorAuthFactorProvider();
}
return $provider;
}
protected function newObjectQuery() {
return new PhabricatorAuthFactorProviderQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create MFA Provider');
}
protected function getObjectCreateButtonText($object) {
return pht('Create MFA Provider');
}
protected function getObjectEditTitleText($object) {
return pht('Edit MFA Provider');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create MFA Provider');
}
protected function getObjectName() {
return pht('MFA Provider');
}
protected function getEditorURI() {
return '/auth/mfa/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/auth/mfa/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AuthManageProvidersCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
$factor_name = $object->getFactor()->getFactorName();
return array(
id(new PhabricatorStaticEditField())
->setKey('displayType')
->setLabel(pht('Factor Type'))
->setDescription(pht('Type of the MFA provider.'))
->setValue($factor_name),
id(new PhabricatorTextEditField())
->setKey('name')
->setTransactionType(
PhabricatorAuthFactorProviderNameTransaction::TRANSACTIONTYPE)
->setLabel(pht('Name'))
->setDescription(pht('Display name for the MFA provider.'))
->setValue($object->getName())
->setPlaceholder($factor_name),
);
}
}

View file

@ -0,0 +1,22 @@
<?php
final class PhabricatorAuthFactorProviderEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function getEditorObjectsDescription() {
return pht('MFA Providers');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this MFA provider.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}

View file

@ -0,0 +1,108 @@
<?php
final class PhabricatorAuthMessageEditEngine
extends PhabricatorEditEngine {
private $messageType;
const ENGINECONST = 'auth.message';
public function isEngineConfigurable() {
return false;
}
public function getEngineName() {
return pht('Auth Messages');
}
public function getSummaryHeader() {
return pht('Edit Auth Messages');
}
public function getSummaryText() {
return pht('This engine is used to edit authentication messages.');
}
public function getEngineApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function setMessageType(PhabricatorAuthMessageType $type) {
$this->messageType = $type;
return $this;
}
public function getMessageType() {
return $this->messageType;
}
protected function newEditableObject() {
$type = $this->getMessageType();
if ($type) {
$message = PhabricatorAuthMessage::initializeNewMessage($type);
} else {
$message = new PhabricatorAuthMessage();
}
return $message;
}
protected function newObjectQuery() {
return new PhabricatorAuthMessageQuery();
}
protected function getObjectCreateTitleText($object) {
return pht('Create Auth Message');
}
protected function getObjectCreateButtonText($object) {
return pht('Create Auth Message');
}
protected function getObjectEditTitleText($object) {
return pht('Edit Auth Message');
}
protected function getObjectEditShortText($object) {
return $object->getObjectName();
}
protected function getObjectCreateShortText() {
return pht('Create Auth Message');
}
protected function getObjectName() {
return pht('Auth Message');
}
protected function getEditorURI() {
return '/auth/message/edit/';
}
protected function getObjectCreateCancelURI($object) {
return '/auth/message/';
}
protected function getObjectViewURI($object) {
return $object->getURI();
}
protected function getCreateNewObjectPolicy() {
return $this->getApplication()->getPolicy(
AuthManageProvidersCapability::CAPABILITY);
}
protected function buildCustomEditFields($object) {
return array(
id(new PhabricatorRemarkupEditField())
->setKey('messageText')
->setTransactionType(
PhabricatorAuthMessageTextTransaction::TRANSACTIONTYPE)
->setLabel(pht('Message Text'))
->setDescription(pht('Custom text for the message.'))
->setValue($object->getMessageText()),
);
}
}

View file

@ -0,0 +1,22 @@
<?php
final class PhabricatorAuthMessageEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
return 'PhabricatorAuthApplication';
}
public function getEditorObjectsDescription() {
return pht('Auth Messages');
}
public function getCreateObjectTitle($author, $object) {
return pht('%s created this message.', $author);
}
public function getCreateObjectTitleForFeed($author, $object) {
return pht('%s created %s.', $author, $object);
}
}

View file

@ -4,6 +4,7 @@ abstract class PhabricatorAuthFactor extends Phobject {
abstract public function getFactorName(); abstract public function getFactorName();
abstract public function getFactorKey(); abstract public function getFactorKey();
abstract public function getFactorCreateHelp();
abstract public function getFactorDescription(); abstract public function getFactorDescription();
abstract public function processAddFactorForm( abstract public function processAddFactorForm(
AphrontFormView $form, AphrontFormView $form,
@ -39,6 +40,11 @@ abstract class PhabricatorAuthFactor extends Phobject {
return new PhabricatorAuthFactorResult(); return new PhabricatorAuthFactorResult();
} }
public function newIconView() {
return id(new PHUIIconView())
->setIcon('fa-mobile');
}
protected function newChallenge( protected function newChallenge(
PhabricatorAuthFactorConfig $config, PhabricatorAuthFactorConfig $config,
PhabricatorUser $viewer) { PhabricatorUser $viewer) {

View file

@ -12,6 +12,12 @@ final class PhabricatorTOTPAuthFactor extends PhabricatorAuthFactor {
return pht('Mobile Phone App (TOTP)'); return pht('Mobile Phone App (TOTP)');
} }
public function getFactorCreateHelp() {
return pht(
'Allow users to attach a mobile authenticator application (like '.
'Google Authenticator) to their account.');
}
public function getFactorDescription() { public function getFactorDescription() {
return pht( return pht(
'Attach a mobile authenticator application (like Authy '. 'Attach a mobile authenticator application (like Authy '.

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthLoginMessageType
extends PhabricatorAuthMessageType {
const MESSAGEKEY = 'auth.login';
public function getDisplayName() {
return pht('Login Screen Instructions');
}
public function getShortDescription() {
return pht(
'Guidance shown on the main login screen before users log in or '.
'register.');
}
}

View file

@ -0,0 +1,32 @@
<?php
abstract class PhabricatorAuthMessageType
extends Phobject {
final public function getMessageTypeKey() {
return $this->getPhobjectClassConstant('MESSAGEKEY', 64);
}
final public static function getAllMessageTypes() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getMessageTypeKey')
->execute();
}
final public static function newFromKey($key) {
$types = self::getAllMessageTypes();
if (empty($types[$key])) {
throw new Exception(
pht(
'No message type exists with key "%s".',
$key));
}
return clone $types[$key];
}
abstract public function getDisplayName();
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthWelcomeMailMessageType
extends PhabricatorAuthMessageType {
const MESSAGEKEY = 'mail.welcome';
public function getDisplayName() {
return pht('Welcome Email Body');
}
public function getShortDescription() {
return pht(
'Custom instructions included in "Welcome" mail when an '.
'administrator creates a user account.');
}
}

View file

@ -0,0 +1,40 @@
<?php
final class PhabricatorAuthAuthFactorProviderPHIDType
extends PhabricatorPHIDType {
const TYPECONST = 'FPRV';
public function getTypeName() {
return pht('MFA Provider');
}
public function newObject() {
return new PhabricatorAuthFactorProvider();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorAuthApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorAuthFactorProviderQuery())
->withPHIDs($phids);
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
foreach ($handles as $phid => $handle) {
$provider = $objects[$phid];
$handle->setURI($provider->getURI());
}
}
}

View file

@ -0,0 +1,32 @@
<?php
final class PhabricatorAuthMessagePHIDType extends PhabricatorPHIDType {
const TYPECONST = 'AMSG';
public function getTypeName() {
return pht('Auth Message');
}
public function newObject() {
return new PhabricatorAuthMessage();
}
public function getPHIDTypeApplicationClass() {
return 'PhabricatorAuthApplication';
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return new PhabricatorAuthMessageQuery();
}
public function loadHandles(
PhabricatorHandleQuery $query,
array $handles,
array $objects) {
return;
}
}

View file

@ -255,18 +255,48 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
$viewer = $request->getUser(); $viewer = $request->getUser();
$content_source = PhabricatorContentSource::newFromRequest($request); $content_source = PhabricatorContentSource::newFromRequest($request);
$captcha_limit = 5;
$hard_limit = 32;
$limit_window = phutil_units('15 minutes in seconds');
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP(
PhabricatorUserLog::ACTION_LOGIN_FAILURE,
$limit_window);
// If the same remote address has submitted several failed login attempts
// recently, require they provide a CAPTCHA response for new attempts.
$require_captcha = false; $require_captcha = false;
$captcha_valid = false; $captcha_valid = false;
if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) { if (AphrontFormRecaptchaControl::isRecaptchaEnabled()) {
$failed_attempts = PhabricatorUserLog::loadRecentEventsFromThisIP( if (count($failed_attempts) > $captcha_limit) {
PhabricatorUserLog::ACTION_LOGIN_FAILURE,
60 * 15);
if (count($failed_attempts) > 5) {
$require_captcha = true; $require_captcha = true;
$captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request); $captcha_valid = AphrontFormRecaptchaControl::processCaptcha($request);
} }
} }
// If the user has submitted quite a few failed login attempts recently,
// give them a hard limit.
if (count($failed_attempts) > $hard_limit) {
$guidance = array();
$guidance[] = pht(
'Your remote address has failed too many login attempts recently. '.
'Wait a few minutes before trying again.');
$guidance[] = pht(
'If you are unable to log in to your account, you can '.
'[[ /login/email | send a reset link to your email address ]].');
$guidance = implode("\n\n", $guidance);
$dialog = $controller->newDialog()
->setTitle(pht('Too Many Login Attempts'))
->appendChild(new PHUIRemarkupView($viewer, $guidance))
->addCancelButton('/auth/start/', pht('Wait Patiently'));
return array(null, $dialog);
}
$response = null; $response = null;
$account = null; $account = null;
$log_user = null; $log_user = null;

View file

@ -0,0 +1,67 @@
<?php
final class PhabricatorAuthFactorProviderQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthFactorProvider();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
return $where;
}
protected function willFilterPage(array $providers) {
$map = PhabricatorAuthFactor::getAllFactors();
foreach ($providers as $key => $provider) {
$factor_key = $provider->getProviderFactorKey();
$factor = idx($map, $factor_key);
if (!$factor) {
unset($providers[$key]);
continue;
}
$provider->attachFactor($factor);
}
return $providers;
}
public function getQueryApplicationClass() {
return 'PhabricatorAuthApplication';
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorAuthFactorProviderTransactionQuery
extends PhabricatorApplicationTransactionQuery {
public function getTemplateApplicationTransaction() {
return new PhabricatorAuthFactorProviderTransaction();
}
}

View file

@ -0,0 +1,83 @@
<?php
final class PhabricatorAuthMessageQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $phids;
private $messageKeys;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withPHIDs(array $phids) {
$this->phids = $phids;
return $this;
}
public function withMessageKeys(array $keys) {
$this->messageKeys = $keys;
return $this;
}
public function newResultObject() {
return new PhabricatorAuthMessage();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->phids !== null) {
$where[] = qsprintf(
$conn,
'phid IN (%Ls)',
$this->phids);
}
if ($this->messageKeys !== null) {
$where[] = qsprintf(
$conn,
'messageKey IN (%Ls)',
$this->messageKeys);
}
return $where;
}
protected function willFilterPage(array $messages) {
$message_types = PhabricatorAuthMessageType::getAllMessageTypes();
foreach ($messages as $key => $message) {
$message_key = $message->getMessageKey();
$message_type = idx($message_types, $message_key);
if (!$message_type) {
unset($messages[$key]);
$this->didRejectResult($message);
continue;
}
$message->attachMessageType($message_type);
}
return $messages;
}
public function getQueryApplicationClass() {
return 'PhabricatorAuthApplication';
}
}

View file

@ -0,0 +1,10 @@
<?php
final class PhabricatorAuthMessageTransactionQuery
extends PhabricatorApplicationTransactionQuery {
public function getTemplateApplicationTransaction() {
return new PhabricatorAuthMessageTransaction();
}
}

View file

@ -0,0 +1,134 @@
<?php
final class PhabricatorAuthFactorProvider
extends PhabricatorAuthDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorExtendedPolicyInterface {
protected $providerFactorKey;
protected $name;
protected $status;
protected $properties = array();
private $factor = self::ATTACHABLE;
const STATUS_ACTIVE = 'active';
const STATUS_DEPRECATED = 'deprecated';
const STATUS_DISABLED = 'disabled';
public static function initializeNewProvider(PhabricatorAuthFactor $factor) {
return id(new self())
->setProviderFactorKey($factor->getFactorKey())
->attachFactor($factor)
->setStatus(self::STATUS_ACTIVE);
}
protected function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'properties' => self::SERIALIZATION_JSON,
),
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'providerFactorKey' => 'text64',
'name' => 'text255',
'status' => 'text32',
),
) + parent::getConfiguration();
}
public function getPHIDType() {
return PhabricatorAuthAuthFactorProviderPHIDType::TYPECONST;
}
public function getURI() {
return '/auth/mfa/'.$this->getID().'/';
}
public function getObjectName() {
return pht('MFA Provider %d', $this->getID());
}
public function getAuthFactorProviderProperty($key, $default = null) {
return idx($this->properties, $key, $default);
}
public function setAuthFactorProviderProperty($key, $value) {
$this->properties[$key] = $value;
return $this;
}
public function attachFactor(PhabricatorAuthFactor $factor) {
$this->factor = $factor;
return $this;
}
public function getFactor() {
return $this->assertAttached($this->factor);
}
public function getDisplayName() {
$name = $this->getName();
if (strlen($name)) {
return $name;
}
return $this->getFactor()->getFactorName();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorAuthFactorProviderEditor();
}
public function getApplicationTransactionTemplate() {
return new PhabricatorAuthFactorProviderTransaction();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
return PhabricatorPolicies::getMostOpenPolicy();
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
$extended = array();
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
break;
case PhabricatorPolicyCapability::CAN_EDIT:
$extended[] = array(
new PhabricatorAuthApplication(),
AuthManageProvidersCapability::CAPABILITY,
);
break;
}
return $extended;
}
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthFactorProviderTransaction
extends PhabricatorModularTransaction {
public function getApplicationName() {
return 'auth';
}
public function getApplicationTransactionType() {
return PhabricatorAuthAuthFactorProviderPHIDType::TYPECONST;
}
public function getBaseTransactionClass() {
return 'PhabricatorAuthFactorProviderTransactionType';
}
}

View file

@ -0,0 +1,138 @@
<?php
final class PhabricatorAuthMessage
extends PhabricatorAuthDAO
implements
PhabricatorApplicationTransactionInterface,
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface {
protected $messageKey;
protected $messageText;
private $messageType = self::ATTACHABLE;
public static function initializeNewMessage(
PhabricatorAuthMessageType $type) {
return id(new self())
->setMessageKey($type->getMessageTypeKey())
->attachMessageType($type);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'messageKey' => 'text64',
'messageText' => 'text',
),
self::CONFIG_KEY_SCHEMA => array(
'key_type' => array(
'columns' => array('messageKey'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getPHIDType() {
return PhabricatorAuthMessagePHIDType::TYPECONST;
}
public function getObjectName() {
return pht('Auth Message %d', $this->getID());
}
public function getURI() {
return urisprintf('/auth/message/%s', $this->getID());
}
public function attachMessageType(PhabricatorAuthMessageType $type) {
$this->messageType = $type;
return $this;
}
public function getMessageType() {
return $this->assertAttached($this->messageType);
}
public function getMessageTypeDisplayName() {
return $this->getMessageType()->getDisplayName();
}
public static function loadMessage(
PhabricatorUser $viewer,
$message_key) {
return id(new PhabricatorAuthMessageQuery())
->setViewer($viewer)
->withMessageKeys(array($message_key))
->executeOne();
}
public static function loadMessageText(
PhabricatorUser $viewer,
$message_key) {
$message = self::loadMessage($viewer, $message_key);
if (!$message) {
return null;
}
return $message->getMessageText();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::getMostOpenPolicy();
default:
return false;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
// Even if an install doesn't allow public users, you can still view
// auth messages: otherwise, we can't do things like show you
// guidance on the login screen.
return true;
default:
return false;
}
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorAuthMessageEditor();
}
public function getApplicationTransactionTemplate() {
return new PhabricatorAuthMessageTransaction();
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->delete();
}
}

View file

@ -0,0 +1,18 @@
<?php
final class PhabricatorAuthMessageTransaction
extends PhabricatorModularTransaction {
public function getApplicationName() {
return 'auth';
}
public function getApplicationTransactionType() {
return PhabricatorAuthMessagePHIDType::TYPECONST;
}
public function getBaseTransactionClass() {
return 'PhabricatorAuthMessageTransactionType';
}
}

View file

@ -0,0 +1,69 @@
<?php
final class PhabricatorAuthFactorProviderNameTransaction
extends PhabricatorAuthFactorProviderTransactionType {
const TRANSACTIONTYPE = 'name';
public function generateOldValue($object) {
return $object->getName();
}
public function applyInternalEffects($object, $value) {
$object->setName($value);
}
public function getTitle() {
$old = $this->getOldValue();
$new = $this->getNewValue();
if (!strlen($old)) {
return pht(
'%s named this provider %s.',
$this->renderAuthor(),
$this->renderNewValue());
} else if (!strlen($new)) {
return pht(
'%s removed the name (%s) of this provider.',
$this->renderAuthor(),
$this->renderOldValue());
} else {
return pht(
'%s renamed this provider from %s to %s.',
$this->renderAuthor(),
$this->renderOldValue(),
$this->renderNewValue());
}
}
public function validateTransactions($object, array $xactions) {
$errors = array();
$max_length = $object->getColumnMaximumByteLength('name');
foreach ($xactions as $xaction) {
$new_value = $xaction->getNewValue();
$new_length = strlen($new_value);
if ($new_length > $max_length) {
$errors[] = $this->newInvalidError(
pht(
'Provider names can not be longer than %s characters.',
new PhutilNumber($max_length)),
$xaction);
}
}
return $errors;
}
public function getTransactionTypeForConduit($xaction) {
return 'name';
}
public function getFieldValuesForConduit($xaction, $data) {
return array(
'old' => $xaction->getOldValue(),
'new' => $xaction->getNewValue(),
);
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PhabricatorAuthFactorProviderTransactionType
extends PhabricatorModularTransactionType {}

View file

@ -0,0 +1,39 @@
<?php
final class PhabricatorAuthMessageTextTransaction
extends PhabricatorAuthMessageTransactionType {
const TRANSACTIONTYPE = 'text';
public function generateOldValue($object) {
return $object->getMessageText();
}
public function applyInternalEffects($object, $value) {
$object->setMessageText($value);
}
public function getTitle() {
return pht(
'%s updated the message text.',
$this->renderAuthor());
}
public function hasChangeDetailView() {
return true;
}
public function getMailDiffSectionHeader() {
return pht('CHANGES TO MESSAGE');
}
public function newChangeDetailView() {
$viewer = $this->getViewer();
return id(new PhabricatorApplicationTransactionTextDiffDetailView())
->setViewer($viewer)
->setOldText($this->getOldValue())
->setNewText($this->getNewValue());
}
}

View file

@ -0,0 +1,4 @@
<?php
abstract class PhabricatorAuthMessageTransactionType
extends PhabricatorModularTransactionType {}

View file

@ -13,7 +13,7 @@ final class PhabricatorCalendarEventMailReceiver
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'E'); $id = (int)substr($pattern, 1);
return id(new PhabricatorCalendarEventQuery()) return id(new PhabricatorCalendarEventQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -46,16 +46,20 @@ final class PhabricatorConduitApplication extends PhabricatorApplication {
public function getRoutes() { public function getRoutes() {
return array( return array(
'/conduit/' => array( '/conduit/' => array(
'(?:query/(?P<queryKey>[^/]+)/)?' => 'PhabricatorConduitListController', $this->getQueryRoutePattern() => 'PhabricatorConduitListController',
'method/(?P<method>[^/]+)/' => 'PhabricatorConduitConsoleController', 'method/(?P<method>[^/]+)/' => 'PhabricatorConduitConsoleController',
'log/(?:query/(?P<queryKey>[^/]+)/)?' => 'log/' => array(
$this->getQueryRoutePattern() =>
'PhabricatorConduitLogController', 'PhabricatorConduitLogController',
'log/view/(?P<view>[^/]+)/' => 'PhabricatorConduitLogController', 'view/(?P<view>[^/]+)/' => 'PhabricatorConduitLogController',
'token/' => 'PhabricatorConduitTokenController', ),
'token/edit/(?:(?P<id>\d+)/)?' => 'token/' => array(
'' => 'PhabricatorConduitTokenController',
'edit/(?:(?P<id>\d+)/)?' =>
'PhabricatorConduitTokenEditController', 'PhabricatorConduitTokenEditController',
'token/terminate/(?:(?P<id>\d+)/)?' => 'terminate/(?:(?P<id>\d+)/)?' =>
'PhabricatorConduitTokenTerminateController', 'PhabricatorConduitTokenTerminateController',
),
'login/' => 'PhabricatorConduitTokenHandshakeController', 'login/' => 'PhabricatorConduitTokenHandshakeController',
), ),
'/api/(?P<method>[^/]+)' => 'PhabricatorConduitAPIController', '/api/(?P<method>[^/]+)' => 'PhabricatorConduitAPIController',

View file

@ -6,6 +6,8 @@ final class PhabricatorConduitLogQuery
private $callerPHIDs; private $callerPHIDs;
private $methods; private $methods;
private $methodStatuses; private $methodStatuses;
private $epochMin;
private $epochMax;
public function withCallerPHIDs(array $phids) { public function withCallerPHIDs(array $phids) {
$this->callerPHIDs = $phids; $this->callerPHIDs = $phids;
@ -22,6 +24,12 @@ final class PhabricatorConduitLogQuery
return $this; return $this;
} }
public function withEpochBetween($epoch_min, $epoch_max) {
$this->epochMin = $epoch_min;
$this->epochMax = $epoch_max;
return $this;
}
public function newResultObject() { public function newResultObject() {
return new PhabricatorConduitMethodCallLog(); return new PhabricatorConduitMethodCallLog();
} }
@ -72,6 +80,20 @@ final class PhabricatorConduitLogQuery
$method_names); $method_names);
} }
if ($this->epochMin !== null) {
$where[] = qsprintf(
$conn,
'dateCreated >= %d',
$this->epochMin);
}
if ($this->epochMax !== null) {
$where[] = qsprintf(
$conn,
'dateCreated <= %d',
$this->epochMax);
}
return $where; return $where;
} }

View file

@ -34,6 +34,12 @@ final class PhabricatorConduitLogSearchEngine
$query->withMethodStatuses($map['statuses']); $query->withMethodStatuses($map['statuses']);
} }
if ($map['epochMin'] || $map['epochMax']) {
$query->withEpochBetween(
$map['epochMin'],
$map['epochMax']);
}
return $query; return $query;
} }
@ -55,6 +61,12 @@ final class PhabricatorConduitLogSearchEngine
->setDescription( ->setDescription(
pht('Find calls to stable, unstable, or deprecated methods.')) pht('Find calls to stable, unstable, or deprecated methods.'))
->setOptions(ConduitAPIMethod::getMethodStatusMap()), ->setOptions(ConduitAPIMethod::getMethodStatusMap()),
id(new PhabricatorSearchDateField())
->setLabel(pht('Called After'))
->setKey('epochMin'),
id(new PhabricatorSearchDateField())
->setLabel(pht('Called Before'))
->setKey('epochMax'),
); );
} }
@ -106,6 +118,62 @@ final class PhabricatorConduitLogSearchEngine
return parent::buildSavedQueryFromBuiltin($query_key); return parent::buildSavedQueryFromBuiltin($query_key);
} }
protected function newExportFields() {
$viewer = $this->requireViewer();
return array(
id(new PhabricatorPHIDExportField())
->setKey('callerPHID')
->setLabel(pht('Caller PHID')),
id(new PhabricatorStringExportField())
->setKey('caller')
->setLabel(pht('Caller')),
id(new PhabricatorStringExportField())
->setKey('method')
->setLabel(pht('Method')),
id(new PhabricatorIntExportField())
->setKey('duration')
->setLabel(pht('Call Duration (us)')),
id(new PhabricatorStringExportField())
->setKey('error')
->setLabel(pht('Error')),
);
}
protected function newExportData(array $logs) {
$viewer = $this->requireViewer();
$phids = array();
foreach ($logs as $log) {
if ($log->getCallerPHID()) {
$phids[] = $log->getCallerPHID();
}
}
$handles = $viewer->loadHandles($phids);
$export = array();
foreach ($logs as $log) {
$caller_phid = $log->getCallerPHID();
if ($caller_phid) {
$caller_name = $handles[$caller_phid]->getName();
} else {
$caller_name = null;
}
$map = array(
'callerPHID' => $caller_phid,
'caller' => $caller_name,
'method' => $log->getMethod(),
'duration' => (int)$log->getDuration(),
'error' => $log->getError(),
);
$export[] = $map;
}
return $export;
}
protected function renderResultList( protected function renderResultList(
array $logs, array $logs,
PhabricatorSavedQuery $query, PhabricatorSavedQuery $query,

View file

@ -203,6 +203,11 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
$mailers_reason = pht( $mailers_reason = pht(
'Inbound and outbound mail is now configured with "cluster.mailers".'); 'Inbound and outbound mail is now configured with "cluster.mailers".');
$prefix_reason = pht(
'Per-application mail subject prefix customization is no longer '.
'directly supported. Prefixes and other strings may be customized with '.
'"translation.override".');
$ancient_config += array( $ancient_config += array(
'phid.external-loaders' => 'phid.external-loaders' =>
pht( pht(
@ -394,6 +399,23 @@ final class PhabricatorExtraConfigSetupCheck extends PhabricatorSetupCheck {
'metamta.insecure-auth-with-reply-to' => pht( 'metamta.insecure-auth-with-reply-to' => pht(
'Authenticating users based on "Reply-To" is no longer supported.'), 'Authenticating users based on "Reply-To" is no longer supported.'),
'phabricator.allow-email-users' => pht(
'Public email is now accepted if the associated address has a '.
'default author, and rejected otherwise.'),
'metamta.conpherence.subject-prefix' => $prefix_reason,
'metamta.differential.subject-prefix' => $prefix_reason,
'metamta.diffusion.subject-prefix' => $prefix_reason,
'metamta.files.subject-prefix' => $prefix_reason,
'metamta.legalpad.subject-prefix' => $prefix_reason,
'metamta.macro.subject-prefix' => $prefix_reason,
'metamta.maniphest.subject-prefix' => $prefix_reason,
'metamta.package.subject-prefix' => $prefix_reason,
'metamta.paste.subject-prefix' => $prefix_reason,
'metamta.pholio.subject-prefix' => $prefix_reason,
'metamta.phriction.subject-prefix' => $prefix_reason,
); );
return $ancient_config; return $ancient_config;

View file

@ -0,0 +1,24 @@
<?php
final class PhabricatorMailSetupCheck extends PhabricatorSetupCheck {
public function getDefaultGroup() {
return self::GROUP_OTHER;
}
protected function executeChecks() {
if (PhabricatorEnv::getEnvConfig('cluster.mailers')) {
return;
}
$message = pht(
'You haven\'t configured mailers yet, so Phabricator won\'t be able '.
'to send outbound mail or receive inbound mail. See the '.
'configuration setting cluster.mailers for details.');
$this->newIssue('cluster.mailers')
->setName(pht('Mailers Not Configured'))
->setMessage($message)
->addPhabricatorConfig('cluster.mailers');
}
}

View file

@ -382,6 +382,34 @@ final class PhabricatorMySQLSetupCheck extends PhabricatorSetupCheck {
new PhutilNumber($delta))); new PhutilNumber($delta)));
} }
$local_infile = $ref->loadRawMySQLConfigValue('local_infile');
if ($local_infile) {
$summary = pht(
'The MySQL "local_infile" option is enabled. This option is '.
'unsafe.');
$message = pht(
'Your MySQL server is configured with the "local_infile" option '.
'enabled. This option allows an attacker who finds an SQL injection '.
'hole to escalate their attack by copying files from the webserver '.
'into the database with "LOAD DATA LOCAL INFILE" queries, then '.
'reading the file content with "SELECT" queries.'.
"\n\n".
'You should disable this option in your %s file, in the %s section:'.
"\n\n".
'%s',
phutil_tag('tt', array(), 'my.cnf'),
phutil_tag('tt', array(), '[mysqld]'),
phutil_tag('pre', array(), 'local_infile=0'));
$this->newIssue('mysql.local_infile')
->setName(pht('Unsafe MySQL "local_infile" Setting Enabled'))
->setSummary($summary)
->setMessage($message)
->setDatabaseRef($ref)
->addMySQLConfig('local_infile');
}
} }
protected function shouldUseMySQLSearchEngine() { protected function shouldUseMySQLSearchEngine() {

View file

@ -112,6 +112,42 @@ final class PhabricatorPHPConfigSetupCheck extends PhabricatorSetupCheck {
->setMessage($message); ->setMessage($message);
} }
if (extension_loaded('mysqli')) {
$infile_key = 'mysqli.allow_local_infile';
} else {
$infile_key = 'mysql.allow_local_infile';
}
if (ini_get($infile_key)) {
$summary = pht(
'Disable unsafe option "%s" in PHP configuration.',
$infile_key);
$message = pht(
'PHP is currently configured to honor requests from any MySQL server '.
'it connects to for the content of any local file.'.
"\n\n".
'This capability supports MySQL "LOAD DATA LOCAL INFILE" queries, but '.
'allows a malicious MySQL server read access to the local disk: the '.
'server can ask the client to send the content of any local file, '.
'and the client will comply.'.
"\n\n".
'Although it is normally difficult for an attacker to convince '.
'Phabricator to connect to a malicious MySQL server, you should '.
'disable this option: this capability is unnecessary and inherently '.
'dangerous.'.
"\n\n".
'To disable this option, set: %s',
phutil_tag('tt', array(), pht('%s = 0', $infile_key)));
$this->newIssue('php.'.$infile_key)
->setName(pht('Unsafe PHP "Local Infile" Configuration'))
->setSummary($summary)
->setMessage($message)
->addPHPConfig($infile_key);
}
} }
} }

View file

@ -234,14 +234,6 @@ EOREMARKUP
$this->newOption('phabricator.cache-namespace', 'string', 'phabricator') $this->newOption('phabricator.cache-namespace', 'string', 'phabricator')
->setLocked(true) ->setLocked(true)
->setDescription(pht('Cache namespace.')), ->setDescription(pht('Cache namespace.')),
$this->newOption('phabricator.allow-email-users', 'bool', false)
->setBoolOptions(
array(
pht('Allow'),
pht('Disallow'),
))
->setDescription(
pht('Allow non-members to interact with tasks over email.')),
$this->newOption('phabricator.silent', 'bool', false) $this->newOption('phabricator.silent', 'bool', false)
->setLocked(true) ->setLocked(true)
->setBoolOptions( ->setBoolOptions(

View file

@ -188,13 +188,10 @@ EODOC
pht('Configuring Outbound Email'))); pht('Configuring Outbound Email')));
return array( return array(
$this->newOption('cluster.mailers', 'cluster.mailers', null) $this->newOption('cluster.mailers', 'cluster.mailers', array())
->setHidden(true) ->setHidden(true)
->setDescription($mailers_description), ->setDescription($mailers_description),
$this->newOption( $this->newOption('metamta.default-address', 'string', null)
'metamta.default-address',
'string',
'noreply@phabricator.example.com')
->setDescription(pht('Default "From" address.')), ->setDescription(pht('Default "From" address.')),
$this->newOption( $this->newOption(
'metamta.one-mail-per-recipient', 'metamta.one-mail-per-recipient',

View file

@ -1,32 +0,0 @@
<?php
final class ConpherenceConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Conpherence');
}
public function getDescription() {
return pht('Configure Conpherence messaging.');
}
public function getIcon() {
return 'fa-comments';
}
public function getGroup() {
return 'apps';
}
public function getOptions() {
return array(
$this->newOption(
'metamta.conpherence.subject-prefix',
'string',
'[Conpherence]')
->setDescription(pht('Subject prefix for Conpherence mail.')),
);
}
}

View file

@ -239,7 +239,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.conpherence.subject-prefix'); return pht('[Conpherence]');
} }
protected function supportsSearch() { protected function supportsSearch() {

View file

@ -13,7 +13,7 @@ final class ConpherenceThreadMailReceiver
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'Z'); $id = (int)substr($pattern, 1);
return id(new ConpherenceThreadQuery()) return id(new ConpherenceThreadQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -13,7 +13,7 @@ final class PhabricatorCountdownMailReceiver
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)substr($pattern, 4); $id = (int)substr($pattern, 1);
return id(new PhabricatorCountdownQuery()) return id(new PhabricatorCountdownQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -228,11 +228,6 @@ EOHELP
"\n\n". "\n\n".
'This sort of workflow is very unusual. Very few installs should '. 'This sort of workflow is very unusual. Very few installs should '.
'need to change this option.')), 'need to change this option.')),
$this->newOption(
'metamta.differential.subject-prefix',
'string',
'[Differential]')
->setDescription(pht('Subject prefix for Differential mail.')),
$this->newOption( $this->newOption(
'metamta.differential.attach-patches', 'metamta.differential.attach-patches',
'bool', 'bool',

View file

@ -81,8 +81,7 @@ final class DifferentialDoorkeeperRevisionFeedStoryPublisher
} }
private function getTitlePrefix(DifferentialRevision $revision) { private function getTitlePrefix(DifferentialRevision $revision) {
$prefix_key = 'metamta.differential.subject-prefix'; return pht('[Differential]');
return PhabricatorEnv::getEnvConfig($prefix_key);
} }
} }

View file

@ -563,7 +563,7 @@ final class DifferentialTransactionEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.differential.subject-prefix'); return pht('[Differential]');
} }
protected function getMailThreadID(PhabricatorLiskDAO $object) { protected function getMailThreadID(PhabricatorLiskDAO $object) {

View file

@ -9,14 +9,16 @@ final class DifferentialCreateMailReceiver
protected function processReceivedMail( protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail, PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) { PhutilEmailAddress $target) {
$author = $this->getAuthor();
$attachments = $mail->getAttachments(); $attachments = $mail->getAttachments();
$files = array(); $files = array();
$errors = array(); $errors = array();
if ($attachments) { if ($attachments) {
$files = id(new PhabricatorFileQuery()) $files = id(new PhabricatorFileQuery())
->setViewer($sender) ->setViewer($author)
->withPHIDs($attachments) ->withPHIDs($attachments)
->execute(); ->execute();
foreach ($files as $index => $file) { foreach ($files as $index => $file) {
@ -37,7 +39,7 @@ final class DifferentialCreateMailReceiver
array( array(
'diff' => $file->loadFileData(), 'diff' => $file->loadFileData(),
)); ));
$call->setUser($sender); $call->setUser($author);
try { try {
$result = $call->execute(); $result = $call->execute();
$diffs[$file->getName()] = $result['uri']; $diffs[$file->getName()] = $result['uri'];
@ -56,7 +58,7 @@ final class DifferentialCreateMailReceiver
array( array(
'diff' => $body, 'diff' => $body,
)); ));
$call->setUser($sender); $call->setUser($author);
try { try {
$result = $call->execute(); $result = $call->execute();
$diffs[pht('Mail Body')] = $result['uri']; $diffs[pht('Mail Body')] = $result['uri'];
@ -67,8 +69,7 @@ final class DifferentialCreateMailReceiver
} }
} }
$subject_prefix = $subject_prefix = pht('[Differential]');
PhabricatorEnv::getEnvConfig('metamta.differential.subject-prefix');
if (count($diffs)) { if (count($diffs)) {
$subject = pht( $subject = pht(
'You successfully created %d diff(s).', 'You successfully created %d diff(s).',
@ -108,10 +109,10 @@ final class DifferentialCreateMailReceiver
} }
id(new PhabricatorMetaMTAMail()) id(new PhabricatorMetaMTAMail())
->addTos(array($sender->getPHID())) ->addTos(array($author->getPHID()))
->setSubject($subject) ->setSubject($subject)
->setSubjectPrefix($subject_prefix) ->setSubjectPrefix($subject_prefix)
->setFrom($sender->getPHID()) ->setFrom($author->getPHID())
->setBody($body->render()) ->setBody($body->render())
->saveAndSend(); ->saveAndSend();
} }

View file

@ -13,7 +13,7 @@ final class DifferentialRevisionMailReceiver
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'D'); $id = (int)substr($pattern, 1);
return id(new DifferentialRevisionQuery()) return id(new DifferentialRevisionQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -37,11 +37,6 @@ final class PhabricatorDiffusionConfigOptions
} }
return array( return array(
$this->newOption(
'metamta.diffusion.subject-prefix',
'string',
'[Diffusion]')
->setDescription(pht('Subject prefix for Diffusion mail.')),
$this->newOption( $this->newOption(
'metamta.diffusion.attach-patches', 'metamta.diffusion.attach-patches',
'bool', 'bool',

View file

@ -172,8 +172,7 @@ final class DiffusionDoorkeeperCommitFeedStoryPublisher
} }
private function getTitlePrefix(PhabricatorRepositoryCommit $commit) { private function getTitlePrefix(PhabricatorRepositoryCommit $commit) {
$prefix_key = 'metamta.diffusion.subject-prefix'; return pht('[Diffusion]');
return PhabricatorEnv::getEnvConfig($prefix_key);
} }
} }

View file

@ -197,11 +197,6 @@ final class PhabricatorFilesConfigOptions
"Set this to a valid Amazon S3 bucket to store files there. You ". "Set this to a valid Amazon S3 bucket to store files there. You ".
"must also configure S3 access keys in the 'Amazon Web Services' ". "must also configure S3 access keys in the 'Amazon Web Services' ".
"group.")), "group.")),
$this->newOption(
'metamta.files.subject-prefix',
'string',
'[File]')
->setDescription(pht('Subject prefix for Files email.')),
$this->newOption('files.enable-imagemagick', 'bool', false) $this->newOption('files.enable-imagemagick', 'bool', false)
->setBoolOptions( ->setBoolOptions(
array( array(

View file

@ -27,7 +27,7 @@ final class PhabricatorFileEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.files.subject-prefix'); return pht('[File]');
} }
protected function getMailTo(PhabricatorLiskDAO $object) { protected function getMailTo(PhabricatorLiskDAO $object) {

View file

@ -9,7 +9,8 @@ final class FileCreateMailReceiver
protected function processReceivedMail( protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail, PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) { PhutilEmailAddress $target) {
$author = $this->getAuthor();
$attachment_phids = $mail->getAttachments(); $attachment_phids = $mail->getAttachments();
if (empty($attachment_phids)) { if (empty($attachment_phids)) {
@ -21,14 +22,18 @@ final class FileCreateMailReceiver
$first_phid = head($attachment_phids); $first_phid = head($attachment_phids);
$mail->setRelatedPHID($first_phid); $mail->setRelatedPHID($first_phid);
$sender = $this->getSender();
if (!$sender) {
return;
}
$attachment_count = count($attachment_phids); $attachment_count = count($attachment_phids);
if ($attachment_count > 1) { if ($attachment_count > 1) {
$subject = pht('You successfully uploaded %d files.', $attachment_count); $subject = pht('You successfully uploaded %d files.', $attachment_count);
} else { } else {
$subject = pht('You successfully uploaded a file.'); $subject = pht('You successfully uploaded a file.');
} }
$subject_prefix = $subject_prefix = pht('[File]');
PhabricatorEnv::getEnvConfig('metamta.files.subject-prefix');
$file_uris = array(); $file_uris = array();
foreach ($attachment_phids as $phid) { foreach ($attachment_phids as $phid) {

View file

@ -12,7 +12,7 @@ final class FileMailReceiver extends PhabricatorObjectMailReceiver {
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'F'); $id = (int)substr($pattern, 1);
return id(new PhabricatorFileQuery()) return id(new PhabricatorFileQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -1,32 +0,0 @@
<?php
final class PhabricatorLegalpadConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Legalpad');
}
public function getDescription() {
return pht('Configure Legalpad.');
}
public function getIcon() {
return 'fa-gavel';
}
public function getGroup() {
return 'apps';
}
public function getOptions() {
return array(
$this->newOption(
'metamta.legalpad.subject-prefix',
'string',
'[Legalpad]')
->setDescription(pht('Subject prefix for Legalpad email.')),
);
}
}

View file

@ -166,7 +166,7 @@ final class LegalpadDocumentEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.legalpad.subject-prefix'); return pht('[Legalpad]');
} }

View file

@ -12,7 +12,7 @@ final class LegalpadMailReceiver extends PhabricatorObjectMailReceiver {
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'L'); $id = (int)substr($pattern, 1);
return id(new LegalpadDocumentQuery()) return id(new LegalpadDocumentQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -1,29 +0,0 @@
<?php
final class PhabricatorMacroConfigOptions
extends PhabricatorApplicationConfigOptions {
public function getName() {
return pht('Macro');
}
public function getDescription() {
return pht('Configure Macro.');
}
public function getIcon() {
return 'fa-file-image-o';
}
public function getGroup() {
return 'apps';
}
public function getOptions() {
return array(
$this->newOption('metamta.macro.subject-prefix', 'string', '[Macro]')
->setDescription(pht('Subject prefix for Macro email.')),
);
}
}

View file

@ -57,7 +57,7 @@ final class PhabricatorMacroEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.macro.subject-prefix'); return pht('[Macro]');
} }
protected function shouldPublishFeedStory( protected function shouldPublishFeedStory(

View file

@ -459,11 +459,6 @@ EOTEXT
'%s configuration option. The default value (`90`) '. '%s configuration option. The default value (`90`) '.
'corresponds to the default "Needs Triage" priority.', 'corresponds to the default "Needs Triage" priority.',
'maniphest.priorities')), 'maniphest.priorities')),
$this->newOption(
'metamta.maniphest.subject-prefix',
'string',
'[Maniphest]')
->setDescription(pht('Subject prefix for Maniphest mail.')),
$this->newOption('maniphest.points', $points_type, array()) $this->newOption('maniphest.points', $points_type, array())
->setSummary(pht('Configure point values for tasks.')) ->setSummary(pht('Configure point values for tasks.'))
->setDescription($points_description) ->setDescription($points_description)

View file

@ -74,8 +74,6 @@ final class ManiphestReportController extends ManiphestController {
$table = new ManiphestTransaction(); $table = new ManiphestTransaction();
$conn = $table->establishConnection('r'); $conn = $table->establishConnection('r');
$joins = '';
$create_joins = '';
if ($project_phid) { if ($project_phid) {
$joins = qsprintf( $joins = qsprintf(
$conn, $conn,
@ -91,6 +89,9 @@ final class ManiphestReportController extends ManiphestController {
PhabricatorEdgeConfig::TABLE_NAME_EDGE, PhabricatorEdgeConfig::TABLE_NAME_EDGE,
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST, PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
$project_phid); $project_phid);
} else {
$joins = qsprintf($conn, '');
$create_joins = qsprintf($conn, '');
} }
$data = queryfx_all( $data = queryfx_all(

View file

@ -155,7 +155,7 @@ final class ManiphestTransactionEditor
} }
protected function getMailSubjectPrefix() { protected function getMailSubjectPrefix() {
return PhabricatorEnv::getEnvConfig('metamta.maniphest.subject-prefix'); return pht('[Maniphest]');
} }
protected function getMailThreadID(PhabricatorLiskDAO $object) { protected function getMailThreadID(PhabricatorLiskDAO $object) {

View file

@ -9,15 +9,20 @@ final class ManiphestCreateMailReceiver
protected function processReceivedMail( protected function processReceivedMail(
PhabricatorMetaMTAReceivedMail $mail, PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) { PhutilEmailAddress $target) {
$task = ManiphestTask::initializeNewTask($sender); $author = $this->getAuthor();
$task->setOriginalEmailSource($mail->getHeader('From')); $task = ManiphestTask::initializeNewTask($author);
$from_address = $mail->newFromAddress();
if ($from_address) {
$task->setOriginalEmailSource((string)$from_address);
}
$handler = new ManiphestReplyHandler(); $handler = new ManiphestReplyHandler();
$handler->setMailReceiver($task); $handler->setMailReceiver($task);
$handler->setActor($sender); $handler->setActor($author);
$handler->setExcludeMailRecipientPHIDs( $handler->setExcludeMailRecipientPHIDs(
$mail->loadAllRecipientPHIDs()); $mail->loadAllRecipientPHIDs());
if ($this->getApplicationEmail()) { if ($this->getApplicationEmail()) {

View file

@ -12,7 +12,7 @@ final class ManiphestTaskMailReceiver extends PhabricatorObjectMailReceiver {
} }
protected function loadObject($pattern, PhabricatorUser $viewer) { protected function loadObject($pattern, PhabricatorUser $viewer) {
$id = (int)trim($pattern, 'T'); $id = (int)substr($pattern, 1);
return id(new ManiphestTaskQuery()) return id(new ManiphestTaskQuery())
->setViewer($viewer) ->setViewer($viewer)

View file

@ -31,13 +31,12 @@ abstract class ManiphestTaskRelationship
$subscriber_phids = $this->loadMergeSubscriberPHIDs($tasks); $subscriber_phids = $this->loadMergeSubscriberPHIDs($tasks);
$xactions[] = id(new ManiphestTransaction()) $xactions[] = id(new ManiphestTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS) ->setTransactionType(ManiphestTaskMergedFromTransaction::TRANSACTIONTYPE)
->setNewValue(array('+' => $subscriber_phids)); ->setNewValue(mpull($tasks, 'getPHID'));
$xactions[] = id(new ManiphestTransaction()) $xactions[] = id(new ManiphestTransaction())
->setTransactionType( ->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
ManiphestTaskMergedFromTransaction::TRANSACTIONTYPE) ->setNewValue(array('+' => $subscriber_phids));
->setNewValue(mpull($tasks, 'getPHID'));
return $xactions; return $xactions;
} }

View file

@ -1,13 +1,16 @@
<?php <?php
abstract class PhabricatorMailImplementationAdapter extends Phobject { abstract class PhabricatorMailAdapter
extends Phobject {
private $key; private $key;
private $priority; private $priority;
private $media;
private $options = array(); private $options = array();
private $supportsInbound = true; private $supportsInbound = true;
private $supportsOutbound = true; private $supportsOutbound = true;
private $mediaMap;
final public function getAdapterType() { final public function getAdapterType() {
return $this->getPhobjectClassConstant('ADAPTERTYPE'); return $this->getPhobjectClassConstant('ADAPTERTYPE');
@ -20,37 +23,61 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
->execute(); ->execute();
} }
abstract public function getSupportedMessageTypes();
abstract public function setFrom($email, $name = ''); abstract public function sendMessage(PhabricatorMailExternalMessage $message);
abstract public function addReplyTo($email, $name = '');
abstract public function addTos(array $emails);
abstract public function addCCs(array $emails);
abstract public function addAttachment($data, $filename, $mimetype);
abstract public function addHeader($header_name, $header_value);
abstract public function setBody($plaintext_body);
abstract public function setHTMLBody($html_body);
abstract public function setSubject($subject);
/** /**
* Some mailers, notably Amazon SES, do not support us setting a specific * Return true if this adapter supports setting a "Message-ID" when sending
* Message-ID header. * email.
*
* This is an ugly implementation detail because mail threading is a horrible
* mess, implemented differently by every client in existence.
*/ */
abstract public function supportsMessageIDHeader(); public function supportsMessageIDHeader() {
return false;
}
final public function supportsMessageType($message_type) {
if ($this->mediaMap === null) {
$media_map = $this->getSupportedMessageTypes();
$media_map = array_fuse($media_map);
/** if ($this->media) {
* Send the message. Generally, this means connecting to some service and $config_map = $this->media;
* handing data to it. $config_map = array_fuse($config_map);
*
* If the adapter determines that the mail will never be deliverable, it $media_map = array_intersect_key($media_map, $config_map);
* should throw a @{class:PhabricatorMetaMTAPermanentFailureException}. }
*
* For temporary failures, throw some other exception or return `false`. $this->mediaMap = $media_map;
* }
* @return bool True on success.
*/ return isset($this->mediaMap[$message_type]);
abstract public function send(); }
final public function setMedia(array $media) {
$native_map = $this->getSupportedMessageTypes();
$native_map = array_fuse($native_map);
foreach ($media as $medium) {
if (!isset($native_map[$medium])) {
throw new Exception(
pht(
'Adapter ("%s") is configured for medium "%s", but this is not '.
'a supported delivery medium. Supported media are: %s.',
$medium,
implode(', ', $native_map)));
}
}
$this->media = $media;
$this->mediaMap = null;
return $this;
}
final public function getMedia() {
return $this->media;
}
final public function setKey($key) { final public function setKey($key) {
$this->key = $key; $this->key = $key;
@ -110,18 +137,4 @@ abstract class PhabricatorMailImplementationAdapter extends Phobject {
abstract public function newDefaultOptions(); abstract public function newDefaultOptions();
public function prepareForSend() {
return;
}
protected function renderAddress($email, $name = null) {
if (strlen($name)) {
return (string)id(new PhutilEmailAddress())
->setDisplayName($name)
->setAddress($email);
} else {
return $email;
}
}
} }

View file

@ -1,21 +1,17 @@
<?php <?php
final class PhabricatorMailImplementationAmazonSESAdapter final class PhabricatorMailAmazonSESAdapter
extends PhabricatorMailImplementationPHPMailerLiteAdapter { extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'ses'; const ADAPTERTYPE = 'ses';
private $message; public function getSupportedMessageTypes() {
private $isHTML; return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
public function prepareForSend() { );
parent::prepareForSend();
$this->mailer->Mailer = 'amazon-ses';
$this->mailer->customMailer = $this;
} }
public function supportsMessageIDHeader() { public function supportsMessageIDHeader() {
// Amazon SES will ignore any Message-ID we provide.
return false; return false;
} }
@ -26,7 +22,6 @@ final class PhabricatorMailImplementationAmazonSESAdapter
'access-key' => 'string', 'access-key' => 'string',
'secret-key' => 'string', 'secret-key' => 'string',
'endpoint' => 'string', 'endpoint' => 'string',
'encoding' => 'string',
)); ));
} }
@ -35,10 +30,27 @@ final class PhabricatorMailImplementationAmazonSESAdapter
'access-key' => null, 'access-key' => null,
'secret-key' => null, 'secret-key' => null,
'endpoint' => null, 'endpoint' => null,
'encoding' => 'base64',
); );
} }
/**
* @phutil-external-symbol class PHPMailerLite
*/
public function sendMessage(PhabricatorMailExternalMessage $message) {
$root = phutil_get_library_root('phabricator');
$root = dirname($root);
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
$mailer = PHPMailerLite::newFromMessage($message);
$mailer->Mailer = 'amazon-ses';
$mailer->customMailer = $this;
$mailer->Send();
}
/** /**
* @phutil-external-symbol class SimpleEmailService * @phutil-external-symbol class SimpleEmailService
*/ */

View file

@ -1,158 +0,0 @@
<?php
/**
* Mail adapter that uses Mailgun's web API to deliver email.
*/
final class PhabricatorMailImplementationMailgunAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'mailgun';
private $params = array();
private $attachments = array();
public function setFrom($email, $name = '') {
$this->params['from'] = $email;
$this->params['from-name'] = $name;
return $this;
}
public function addReplyTo($email, $name = '') {
if (empty($this->params['reply-to'])) {
$this->params['reply-to'] = array();
}
$this->params['reply-to'][] = $this->renderAddress($email, $name);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->params['tos'][] = $email;
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->params['ccs'][] = $email;
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
$this->attachments[] = array(
'data' => $data,
'name' => $filename,
'type' => $mimetype,
);
return $this;
}
public function addHeader($header_name, $header_value) {
$this->params['headers'][] = array($header_name, $header_value);
return $this;
}
public function setBody($body) {
$this->params['body'] = $body;
return $this;
}
public function setHTMLBody($html_body) {
$this->params['html-body'] = $html_body;
return $this;
}
public function setSubject($subject) {
$this->params['subject'] = $subject;
return $this;
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'api-key' => 'string',
'domain' => 'string',
));
}
public function newDefaultOptions() {
return array(
'api-key' => null,
'domain' => null,
);
}
public function send() {
$key = $this->getOption('api-key');
$domain = $this->getOption('domain');
$params = array();
$params['to'] = implode(', ', idx($this->params, 'tos', array()));
$params['subject'] = idx($this->params, 'subject');
$params['text'] = idx($this->params, 'body');
if (idx($this->params, 'html-body')) {
$params['html'] = idx($this->params, 'html-body');
}
$from = idx($this->params, 'from');
$from_name = idx($this->params, 'from-name');
$params['from'] = $this->renderAddress($from, $from_name);
if (idx($this->params, 'reply-to')) {
$replyto = $this->params['reply-to'];
$params['h:reply-to'] = implode(', ', $replyto);
}
if (idx($this->params, 'ccs')) {
$params['cc'] = implode(', ', $this->params['ccs']);
}
foreach (idx($this->params, 'headers', array()) as $header) {
list($name, $value) = $header;
$params['h:'.$name] = $value;
}
$future = new HTTPSFuture(
"https://api:{$key}@api.mailgun.net/v2/{$domain}/messages",
$params);
$future->setMethod('POST');
foreach ($this->attachments as $attachment) {
$future->attachFileData(
'attachment',
$attachment['data'],
$attachment['name'],
$attachment['type']);
}
list($body) = $future->resolvex();
$response = null;
try {
$response = phutil_json_decode($body);
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to JSON decode response.'),
$ex);
}
if (!idx($response, 'id')) {
$message = $response['message'];
throw new Exception(
pht(
'Request failed with errors: %s.',
$message));
}
return true;
}
}

View file

@ -1,150 +0,0 @@
<?php
final class PhabricatorMailImplementationPHPMailerAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'smtp';
private $mailer;
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'host' => 'string|null',
'port' => 'int',
'user' => 'string|null',
'password' => 'string|null',
'protocol' => 'string|null',
'encoding' => 'string',
'mailer' => 'string',
));
}
public function newDefaultOptions() {
return array(
'host' => null,
'port' => 25,
'user' => null,
'password' => null,
'protocol' => null,
'encoding' => 'base64',
'mailer' => 'smtp',
);
}
/**
* @phutil-external-symbol class PHPMailer
*/
public function prepareForSend() {
$root = phutil_get_library_root('phabricator');
$root = dirname($root);
require_once $root.'/externals/phpmailer/class.phpmailer.php';
$this->mailer = new PHPMailer($use_exceptions = true);
$this->mailer->CharSet = 'utf-8';
$encoding = $this->getOption('encoding');
$this->mailer->Encoding = $encoding;
// By default, PHPMailer sends one mail per recipient. We handle
// combining or separating To and Cc higher in the stack, so tell it to
// send mail exactly like we ask.
$this->mailer->SingleTo = false;
$mailer = $this->getOption('mailer');
if ($mailer == 'smtp') {
$this->mailer->IsSMTP();
$this->mailer->Host = $this->getOption('host');
$this->mailer->Port = $this->getOption('port');
$user = $this->getOption('user');
if ($user) {
$this->mailer->SMTPAuth = true;
$this->mailer->Username = $user;
$this->mailer->Password = $this->getOption('password');
}
$protocol = $this->getOption('protocol');
if ($protocol) {
$protocol = phutil_utf8_strtolower($protocol);
$this->mailer->SMTPSecure = $protocol;
}
} else if ($mailer == 'sendmail') {
$this->mailer->IsSendmail();
} else {
// Do nothing, by default PHPMailer send message using PHP mail()
// function.
}
}
public function supportsMessageIDHeader() {
return true;
}
public function setFrom($email, $name = '') {
$this->mailer->SetFrom($email, $name, $crazy_side_effects = false);
return $this;
}
public function addReplyTo($email, $name = '') {
$this->mailer->AddReplyTo($email, $name);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->mailer->AddAddress($email);
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->mailer->AddCC($email);
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
$this->mailer->AddStringAttachment(
$data,
$filename,
'base64',
$mimetype);
return $this;
}
public function addHeader($header_name, $header_value) {
if (strtolower($header_name) == 'message-id') {
$this->mailer->MessageID = $header_value;
} else {
$this->mailer->AddCustomHeader($header_name.': '.$header_value);
}
return $this;
}
public function setBody($body) {
$this->mailer->IsHTML(false);
$this->mailer->Body = $body;
return $this;
}
public function setHTMLBody($html_body) {
$this->mailer->IsHTML(true);
$this->mailer->Body = $html_body;
return $this;
}
public function setSubject($subject) {
$this->mailer->Subject = $subject;
return $this;
}
public function hasValidRecipients() {
return true;
}
public function send() {
return $this->mailer->Send();
}
}

View file

@ -1,123 +0,0 @@
<?php
/**
* TODO: Should be final, but inherited by SES.
*/
class PhabricatorMailImplementationPHPMailerLiteAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'sendmail';
protected $mailer;
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'encoding' => 'string',
));
}
public function newDefaultOptions() {
return array(
'encoding' => 'base64',
);
}
/**
* @phutil-external-symbol class PHPMailerLite
*/
public function prepareForSend() {
$root = phutil_get_library_root('phabricator');
$root = dirname($root);
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
$this->mailer = new PHPMailerLite($use_exceptions = true);
$this->mailer->CharSet = 'utf-8';
$encoding = $this->getOption('encoding');
$this->mailer->Encoding = $encoding;
// By default, PHPMailerLite sends one mail per recipient. We handle
// combining or separating To and Cc higher in the stack, so tell it to
// send mail exactly like we ask.
$this->mailer->SingleTo = false;
}
public function supportsMessageIDHeader() {
return true;
}
public function setFrom($email, $name = '') {
$this->mailer->SetFrom($email, $name, $crazy_side_effects = false);
return $this;
}
public function addReplyTo($email, $name = '') {
$this->mailer->AddReplyTo($email, $name);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->mailer->AddAddress($email);
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->mailer->AddCC($email);
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
$this->mailer->AddStringAttachment(
$data,
$filename,
'base64',
$mimetype);
return $this;
}
public function addHeader($header_name, $header_value) {
if (strtolower($header_name) == 'message-id') {
$this->mailer->MessageID = $header_value;
} else {
$this->mailer->AddCustomHeader($header_name.': '.$header_value);
}
return $this;
}
public function setBody($body) {
$this->mailer->Body = $body;
$this->mailer->IsHTML(false);
return $this;
}
/**
* Note: phpmailer-lite does NOT support sending messages with mixed version
* (plaintext and html). So for now lets just use HTML if it's available.
* @param $html
*/
public function setHTMLBody($html_body) {
$this->mailer->Body = $html_body;
$this->mailer->IsHTML(true);
return $this;
}
public function setSubject($subject) {
$this->mailer->Subject = $subject;
return $this;
}
public function hasValidRecipients() {
return true;
}
public function send() {
return $this->mailer->Send();
}
}

View file

@ -1,120 +0,0 @@
<?php
final class PhabricatorMailImplementationPostmarkAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'postmark';
private $parameters = array();
public function setFrom($email, $name = '') {
$this->parameters['From'] = $this->renderAddress($email, $name);
return $this;
}
public function addReplyTo($email, $name = '') {
$this->parameters['ReplyTo'] = $this->renderAddress($email, $name);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->parameters['To'][] = $email;
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->parameters['Cc'][] = $email;
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
$this->parameters['Attachments'][] = array(
'Name' => $filename,
'ContentType' => $mimetype,
'Content' => base64_encode($data),
);
return $this;
}
public function addHeader($header_name, $header_value) {
$this->parameters['Headers'][] = array(
'Name' => $header_name,
'Value' => $header_value,
);
return $this;
}
public function setBody($body) {
$this->parameters['TextBody'] = $body;
return $this;
}
public function setHTMLBody($html_body) {
$this->parameters['HtmlBody'] = $html_body;
return $this;
}
public function setSubject($subject) {
$this->parameters['Subject'] = $subject;
return $this;
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'access-token' => 'string',
'inbound-addresses' => 'list<string>',
));
// Make sure this is properly formatted.
PhutilCIDRList::newList($options['inbound-addresses']);
}
public function newDefaultOptions() {
return array(
'access-token' => null,
'inbound-addresses' => array(
// Via Postmark support circa February 2018, see:
//
// https://postmarkapp.com/support/article/800-ips-for-firewalls
//
// "Configuring Outbound Email" should be updated if this changes.
'50.31.156.6/32',
),
);
}
public function send() {
$access_token = $this->getOption('access-token');
$parameters = $this->parameters;
$flatten = array(
'To',
'Cc',
);
foreach ($flatten as $key) {
if (isset($parameters[$key])) {
$parameters[$key] = implode(', ', $parameters[$key]);
}
}
id(new PhutilPostmarkFuture())
->setAccessToken($access_token)
->setMethod('email', $parameters)
->resolve();
return true;
}
}

View file

@ -1,173 +0,0 @@
<?php
/**
* Mail adapter that uses SendGrid's web API to deliver email.
*/
final class PhabricatorMailImplementationSendGridAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'sendgrid';
private $params = array();
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'api-user' => 'string',
'api-key' => 'string',
));
}
public function newDefaultOptions() {
return array(
'api-user' => null,
'api-key' => null,
);
}
public function setFrom($email, $name = '') {
$this->params['from'] = $email;
$this->params['from-name'] = $name;
return $this;
}
public function addReplyTo($email, $name = '') {
if (empty($this->params['reply-to'])) {
$this->params['reply-to'] = array();
}
$this->params['reply-to'][] = array(
'email' => $email,
'name' => $name,
);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->params['tos'][] = $email;
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->params['ccs'][] = $email;
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
if (empty($this->params['files'])) {
$this->params['files'] = array();
}
$this->params['files'][$filename] = $data;
}
public function addHeader($header_name, $header_value) {
$this->params['headers'][] = array($header_name, $header_value);
return $this;
}
public function setBody($body) {
$this->params['body'] = $body;
return $this;
}
public function setHTMLBody($body) {
$this->params['html-body'] = $body;
return $this;
}
public function setSubject($subject) {
$this->params['subject'] = $subject;
return $this;
}
public function supportsMessageIDHeader() {
return false;
}
public function send() {
$user = $this->getOption('api-user');
$key = $this->getOption('api-key');
$params = array();
$ii = 0;
foreach (idx($this->params, 'tos', array()) as $to) {
$params['to['.($ii++).']'] = $to;
}
$params['subject'] = idx($this->params, 'subject');
$params['text'] = idx($this->params, 'body');
if (idx($this->params, 'html-body')) {
$params['html'] = idx($this->params, 'html-body');
}
$params['from'] = idx($this->params, 'from');
if (idx($this->params, 'from-name')) {
$params['fromname'] = $this->params['from-name'];
}
if (idx($this->params, 'reply-to')) {
$replyto = $this->params['reply-to'];
// Pick off the email part, no support for the name part in this API.
$params['replyto'] = $replyto[0]['email'];
}
foreach (idx($this->params, 'files', array()) as $name => $data) {
$params['files['.$name.']'] = $data;
}
$headers = idx($this->params, 'headers', array());
// See SendGrid Support Ticket #29390; there's no explicit REST API support
// for CC right now but it works if you add a generic "Cc" header.
//
// SendGrid said this is supported:
// "You can use CC as you are trying to do there [by adding a generic
// header]. It is supported despite our limited documentation to this
// effect, I am glad you were able to figure it out regardless. ..."
if (idx($this->params, 'ccs')) {
$headers[] = array('Cc', implode(', ', $this->params['ccs']));
}
if ($headers) {
// Convert to dictionary.
$headers = ipull($headers, 1, 0);
$headers = json_encode($headers);
$params['headers'] = $headers;
}
$params['api_user'] = $user;
$params['api_key'] = $key;
$future = new HTTPSFuture(
'https://sendgrid.com/api/mail.send.json',
$params);
$future->setMethod('POST');
list($body) = $future->resolvex();
$response = null;
try {
$response = phutil_json_decode($body);
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to JSON decode response.'),
$ex);
}
if ($response['message'] !== 'success') {
$errors = implode(';', $response['errors']);
throw new Exception(pht('Request failed with errors: %s.', $errors));
}
return true;
}
}

View file

@ -1,130 +0,0 @@
<?php
/**
* Mail adapter that doesn't actually send any email, for writing unit tests
* against.
*/
final class PhabricatorMailImplementationTestAdapter
extends PhabricatorMailImplementationAdapter {
const ADAPTERTYPE = 'test';
private $guts = array();
private $config = array();
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array());
}
public function newDefaultOptions() {
return array();
}
public function prepareForSend(array $config = array()) {
$this->config = $config;
}
public function setFrom($email, $name = '') {
$this->guts['from'] = $email;
$this->guts['from-name'] = $name;
return $this;
}
public function addReplyTo($email, $name = '') {
if (empty($this->guts['reply-to'])) {
$this->guts['reply-to'] = array();
}
$this->guts['reply-to'][] = array(
'email' => $email,
'name' => $name,
);
return $this;
}
public function addTos(array $emails) {
foreach ($emails as $email) {
$this->guts['tos'][] = $email;
}
return $this;
}
public function addCCs(array $emails) {
foreach ($emails as $email) {
$this->guts['ccs'][] = $email;
}
return $this;
}
public function addAttachment($data, $filename, $mimetype) {
$this->guts['attachments'][] = array(
'data' => $data,
'filename' => $filename,
'mimetype' => $mimetype,
);
return $this;
}
public function addHeader($header_name, $header_value) {
$this->guts['headers'][] = array($header_name, $header_value);
return $this;
}
public function setBody($body) {
$this->guts['body'] = $body;
return $this;
}
public function setHTMLBody($html_body) {
$this->guts['html-body'] = $html_body;
return $this;
}
public function setSubject($subject) {
$this->guts['subject'] = $subject;
return $this;
}
public function supportsMessageIDHeader() {
return idx($this->config, 'supportsMessageIDHeader', true);
}
public function send() {
if (!empty($this->guts['fail-permanently'])) {
throw new PhabricatorMetaMTAPermanentFailureException(
pht('Unit Test (Permanent)'));
}
if (!empty($this->guts['fail-temporarily'])) {
throw new Exception(
pht('Unit Test (Temporary)'));
}
$this->guts['did-send'] = true;
return true;
}
public function getGuts() {
return $this->guts;
}
public function setFailPermanently($fail) {
$this->guts['fail-permanently'] = $fail;
return $this;
}
public function setFailTemporarily($fail) {
$this->guts['fail-temporarily'] = $fail;
return $this;
}
public function getBody() {
return idx($this->guts, 'body');
}
public function getHTMLBody() {
return idx($this->guts, 'html-body');
}
}

View file

@ -0,0 +1,132 @@
<?php
/**
* Mail adapter that uses Mailgun's web API to deliver email.
*/
final class PhabricatorMailMailgunAdapter
extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'mailgun';
public function getSupportedMessageTypes() {
return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
);
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'api-key' => 'string',
'domain' => 'string',
));
}
public function newDefaultOptions() {
return array(
'api-key' => null,
'domain' => null,
);
}
public function sendMessage(PhabricatorMailExternalMessage $message) {
$api_key = $this->getOption('api-key');
$domain = $this->getOption('domain');
$params = array();
$subject = $message->getSubject();
if ($subject !== null) {
$params['subject'] = $subject;
}
$from_address = $message->getFromAddress();
if ($from_address) {
$params['from'] = (string)$from_address;
}
$to_addresses = $message->getToAddresses();
if ($to_addresses) {
$to = array();
foreach ($to_addresses as $address) {
$to[] = (string)$address;
}
$params['to'] = implode(', ', $to);
}
$cc_addresses = $message->getCCAddresses();
if ($cc_addresses) {
$cc = array();
foreach ($cc_addresses as $address) {
$cc[] = (string)$address;
}
$params['cc'] = implode(', ', $cc);
}
$reply_address = $message->getReplyToAddress();
if ($reply_address) {
$params['h:reply-to'] = (string)$reply_address;
}
$headers = $message->getHeaders();
if ($headers) {
foreach ($headers as $header) {
$name = $header->getName();
$value = $header->getValue();
$params['h:'.$name] = $value;
}
}
$text_body = $message->getTextBody();
if ($text_body !== null) {
$params['text'] = $text_body;
}
$html_body = $message->getHTMLBody();
if ($html_body !== null) {
$params['html'] = $html_body;
}
$mailgun_uri = urisprintf(
'https://api.mailgun.net/v2/%s/messages',
$domain);
$future = id(new HTTPSFuture($mailgun_uri, $params))
->setMethod('POST')
->setHTTPBasicAuthCredentials('api', new PhutilOpaqueEnvelope($api_key))
->setTimeout(60);
$attachments = $message->getAttachments();
foreach ($attachments as $attachment) {
$future->attachFileData(
'attachment',
$attachment->getData(),
$attachment->getFilename(),
$attachment->getMimeType());
}
list($body) = $future->resolvex();
$response = null;
try {
$response = phutil_json_decode($body);
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht('Failed to JSON decode response.'),
$ex);
}
if (!idx($response, 'id')) {
$message = $response['message'];
throw new Exception(
pht(
'Request failed with errors: %s.',
$message));
}
}
}

View file

@ -0,0 +1,128 @@
<?php
final class PhabricatorMailPostmarkAdapter
extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'postmark';
public function getSupportedMessageTypes() {
return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
);
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'access-token' => 'string',
'inbound-addresses' => 'list<string>',
));
// Make sure this is properly formatted.
PhutilCIDRList::newList($options['inbound-addresses']);
}
public function newDefaultOptions() {
return array(
'access-token' => null,
'inbound-addresses' => array(
// Via Postmark support circa February 2018, see:
//
// https://postmarkapp.com/support/article/800-ips-for-firewalls
//
// "Configuring Outbound Email" should be updated if this changes.
//
// These addresses were last updated in January 2019.
'50.31.156.6/32',
'50.31.156.77/32',
'18.217.206.57/32',
),
);
}
public function sendMessage(PhabricatorMailExternalMessage $message) {
$access_token = $this->getOption('access-token');
$parameters = array();
$subject = $message->getSubject();
if ($subject !== null) {
$parameters['Subject'] = $subject;
}
$from_address = $message->getFromAddress();
if ($from_address) {
$parameters['From'] = (string)$from_address;
}
$to_addresses = $message->getToAddresses();
if ($to_addresses) {
$to = array();
foreach ($to_addresses as $address) {
$to[] = (string)$address;
}
$parameters['To'] = implode(', ', $to);
}
$cc_addresses = $message->getCCAddresses();
if ($cc_addresses) {
$cc = array();
foreach ($cc_addresses as $address) {
$cc[] = (string)$address;
}
$parameters['Cc'] = implode(', ', $cc);
}
$reply_address = $message->getReplyToAddress();
if ($reply_address) {
$parameters['ReplyTo'] = (string)$reply_address;
}
$headers = $message->getHeaders();
if ($headers) {
$list = array();
foreach ($headers as $header) {
$list[] = array(
'Name' => $header->getName(),
'Value' => $header->getValue(),
);
}
$parameters['Headers'] = $list;
}
$text_body = $message->getTextBody();
if ($text_body !== null) {
$parameters['TextBody'] = $text_body;
}
$html_body = $message->getHTMLBody();
if ($html_body !== null) {
$parameters['HtmlBody'] = $html_body;
}
$attachments = $message->getAttachments();
if ($attachments) {
$files = array();
foreach ($attachments as $attachment) {
$files[] = array(
'Name' => $attachment->getFilename(),
'ContentType' => $attachment->getMimeType(),
'Content' => base64_encode($attachment->getData()),
);
}
$parameters['Attachments'] = $files;
}
id(new PhutilPostmarkFuture())
->setAccessToken($access_token)
->setMethod('email', $parameters)
->setTimeout(60)
->resolve();
}
}

View file

@ -0,0 +1,154 @@
<?php
final class PhabricatorMailSMTPAdapter
extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'smtp';
public function getSupportedMessageTypes() {
return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
);
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'host' => 'string|null',
'port' => 'int',
'user' => 'string|null',
'password' => 'string|null',
'protocol' => 'string|null',
));
}
public function newDefaultOptions() {
return array(
'host' => null,
'port' => 25,
'user' => null,
'password' => null,
'protocol' => null,
);
}
/**
* @phutil-external-symbol class PHPMailer
*/
public function sendMessage(PhabricatorMailExternalMessage $message) {
$root = phutil_get_library_root('phabricator');
$root = dirname($root);
require_once $root.'/externals/phpmailer/class.phpmailer.php';
$smtp = new PHPMailer($use_exceptions = true);
$smtp->CharSet = 'utf-8';
$smtp->Encoding = 'base64';
// By default, PHPMailer sends one mail per recipient. We handle
// combining or separating To and Cc higher in the stack, so tell it to
// send mail exactly like we ask.
$smtp->SingleTo = false;
$smtp->IsSMTP();
$smtp->Host = $this->getOption('host');
$smtp->Port = $this->getOption('port');
$user = $this->getOption('user');
if (strlen($user)) {
$smtp->SMTPAuth = true;
$smtp->Username = $user;
$smtp->Password = $this->getOption('password');
}
$protocol = $this->getOption('protocol');
if ($protocol) {
$protocol = phutil_utf8_strtolower($protocol);
$smtp->SMTPSecure = $protocol;
}
$subject = $message->getSubject();
if ($subject !== null) {
$smtp->Subject = $subject;
}
$from_address = $message->getFromAddress();
if ($from_address) {
$smtp->SetFrom(
$from_address->getAddress(),
(string)$from_address->getDisplayName(),
$crazy_side_effects = false);
}
$reply_address = $message->getReplyToAddress();
if ($reply_address) {
$smtp->AddReplyTo(
$reply_address->getAddress(),
(string)$reply_address->getDisplayName());
}
$to_addresses = $message->getToAddresses();
if ($to_addresses) {
foreach ($to_addresses as $address) {
$smtp->AddAddress(
$address->getAddress(),
(string)$address->getDisplayName());
}
}
$cc_addresses = $message->getCCAddresses();
if ($cc_addresses) {
foreach ($cc_addresses as $address) {
$smtp->AddCC(
$address->getAddress(),
(string)$address->getDisplayName());
}
}
$headers = $message->getHeaders();
if ($headers) {
$list = array();
foreach ($headers as $header) {
$name = $header->getName();
$value = $header->getValue();
if (phutil_utf8_strtolower($name) === 'message-id') {
$smtp->MessageID = $value;
} else {
$smtp->AddCustomHeader("{$name}: {$value}");
}
}
}
$text_body = $message->getTextBody();
if ($text_body !== null) {
$smtp->Body = $text_body;
}
$html_body = $message->getHTMLBody();
if ($html_body !== null) {
$smtp->IsHTML(true);
$smtp->Body = $html_body;
if ($text_body !== null) {
$smtp->AltBody = $text_body;
}
}
$attachments = $message->getAttachments();
if ($attachments) {
foreach ($attachments as $attachment) {
$smtp->AddStringAttachment(
$attachment->getData(),
$attachment->getFilename(),
'base64',
$attachment->getMimeType());
}
}
$smtp->Send();
}
}

View file

@ -0,0 +1,144 @@
<?php
/**
* Mail adapter that uses SendGrid's web API to deliver email.
*/
final class PhabricatorMailSendGridAdapter
extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'sendgrid';
public function getSupportedMessageTypes() {
return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
);
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'api-key' => 'string',
));
}
public function newDefaultOptions() {
return array(
'api-key' => null,
);
}
public function sendMessage(PhabricatorMailExternalMessage $message) {
$key = $this->getOption('api-key');
$parameters = array();
$subject = $message->getSubject();
if ($subject !== null) {
$parameters['subject'] = $subject;
}
$personalizations = array();
$to_addresses = $message->getToAddresses();
if ($to_addresses) {
$personalizations['to'] = array();
foreach ($to_addresses as $address) {
$personalizations['to'][] = $this->newPersonalization($address);
}
}
$cc_addresses = $message->getCCAddresses();
if ($cc_addresses) {
$personalizations['cc'] = array();
foreach ($cc_addresses as $address) {
$personalizations['cc'][] = $this->newPersonalization($address);
}
}
// This is a list of different sets of recipients who should receive copies
// of the mail. We handle "one message to each recipient" ourselves.
$parameters['personalizations'] = array(
$personalizations,
);
$from_address = $message->getFromAddress();
if ($from_address) {
$parameters['from'] = $this->newPersonalization($from_address);
}
$reply_address = $message->getReplyToAddress();
if ($reply_address) {
$parameters['reply_to'] = $this->newPersonalization($reply_address);
}
$headers = $message->getHeaders();
if ($headers) {
$map = array();
foreach ($headers as $header) {
$map[$header->getName()] = $header->getValue();
}
$parameters['headers'] = $map;
}
$content = array();
$text_body = $message->getTextBody();
if ($text_body !== null) {
$content[] = array(
'type' => 'text/plain',
'value' => $text_body,
);
}
$html_body = $message->getHTMLBody();
if ($html_body !== null) {
$content[] = array(
'type' => 'text/html',
'value' => $html_body,
);
}
$parameters['content'] = $content;
$attachments = $message->getAttachments();
if ($attachments) {
$files = array();
foreach ($attachments as $attachment) {
$files[] = array(
'content' => base64_encode($attachment->getData()),
'type' => $attachment->getMimeType(),
'filename' => $attachment->getFilename(),
'disposition' => 'attachment',
);
}
$parameters['attachments'] = $files;
}
$sendgrid_uri = 'https://api.sendgrid.com/v3/mail/send';
$json_parameters = phutil_json_encode($parameters);
id(new HTTPSFuture($sendgrid_uri))
->setMethod('POST')
->addHeader('Authorization', "Bearer {$key}")
->addHeader('Content-Type', 'application/json')
->setData($json_parameters)
->setTimeout(60)
->resolvex();
// The SendGrid v3 API does not return a JSON response body. We get a
// non-2XX HTTP response in the case of an error, which throws above.
}
private function newPersonalization(PhutilEmailAddress $address) {
$result = array(
'email' => $address->getAddress(),
);
$display_name = $address->getDisplayName();
if ($display_name) {
$result['name'] = $display_name;
}
return $result;
}
}

View file

@ -0,0 +1,45 @@
<?php
final class PhabricatorMailSendmailAdapter
extends PhabricatorMailAdapter {
const ADAPTERTYPE = 'sendmail';
public function getSupportedMessageTypes() {
return array(
PhabricatorMailEmailMessage::MESSAGETYPE,
);
}
public function supportsMessageIDHeader() {
return true;
}
protected function validateOptions(array $options) {
PhutilTypeSpec::checkMap(
$options,
array(
'encoding' => 'string',
));
}
public function newDefaultOptions() {
return array(
'encoding' => 'base64',
);
}
/**
* @phutil-external-symbol class PHPMailerLite
*/
public function sendMessage(PhabricatorMailExternalMessage $message) {
$root = phutil_get_library_root('phabricator');
$root = dirname($root);
require_once $root.'/externals/phpmailer/class.phpmailer-lite.php';
$mailer = PHPMailerLite::newFromMessage($message);
$mailer->Send();
}
}

Some files were not shown because too many files have changed in this diff Show more