Compare commits
	
		
			568 Commits
		
	
	
		
			blender-tw
			...
			blender-tw
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 436e69f1d0 | ||
| 5db4b6f01a | |||
| 5aabb434b1 | |||
| eced78a591 | |||
| fb3e6ba493 | |||
| 284204e6bb | |||
| 1df20d771c | |||
| 6fa976f749 | |||
| 8808cf8e8c | |||
| f72b9824f3 | |||
| ac94643ac7 | |||
| ce3c14919d | |||
| c9fb4c2945 | |||
| 57099f29d1 | |||
| acfdc33789 | |||
| a5efb1e8cd | |||
| e0bd65be95 | |||
| 1bcc201b0a | |||
| b2d7879162 | |||
| 775a1c2eef | |||
| bd07cea6a6 | |||
| 6139ce1841 | |||
| c38766c17f | |||
|   | d203a1004c | ||
|   | 5b1dd96e40 | ||
|   | 36075f6ce5 | ||
|   | f686a0b827 | ||
|   | a529efa5b8 | ||
|   | 3635a11f84 | ||
|   | 959a835b95 | ||
|   | 4fd0628fae | ||
|   | 87fb35abb7 | ||
|   | 66566f878d | ||
|   | d3d41324be | ||
|   | 6d0dbeb77f | ||
|   | 5d0ae283a9 | ||
|   | d2d7e7f5ff | ||
|   | 10f241352d | ||
|   | 846562158a | ||
|   | 00430fdbe1 | ||
|   | 4b2a447003 | ||
|   | 87bc30526b | ||
|   | 9d5b8bd14a | ||
|   | 4257b26abc | ||
|   | 43a8d8763d | ||
|   | 86d6abe9db | ||
|   | 770a5c8412 | ||
|   | 6cf017d680 | ||
|   | 0c51885cf7 | ||
|   | f86d822a37 | ||
|   | 7b0db3eb54 | ||
|   | 93b08f0e83 | ||
|   | e959f93489 | ||
|   | c666cb9f0b | ||
|   | b1351d0fdb | ||
|   | 3ee6b5393c | ||
|   | fbd57ad832 | ||
|   | b021da71a5 | ||
|   | 42f1a95a12 | ||
|   | f45519c060 | ||
|   | cfb5de6fa7 | ||
|   | 2f5398796e | ||
|   | ebef22ccc1 | ||
|   | 42378ea393 | ||
|   | c063e0e5ec | ||
|   | 419b7ceebb | ||
|   | 1da54837ea | ||
|   | 3dea92081b | ||
|   | df139f044b | ||
|   | e8109e4a92 | ||
|   | acc1fa1655 | ||
|   | 0cca40db3b | ||
|   | 6dc20d1e2e | ||
|   | e7ebd5d9d1 | ||
|   | b804e8cffa | ||
|   | 24ba66f106 | ||
|   | fa2d30ee36 | ||
|   | 94a95efa05 | ||
|   | 79107574a7 | ||
|   | 983d77848b | ||
|   | af5b94b234 | ||
|   | 949b9163d0 | ||
|   | 6c59db20a3 | ||
|   | d0593a5a78 | ||
|   | c1f1345cc0 | ||
|   | 1656a2ff08 | ||
|   | 397648855f | ||
|   | 0067f1a521 | ||
|   | a590db28b2 | ||
|   | 6b69102990 | ||
|   | 6430d6d638 | ||
|   | 07e160bde1 | ||
|   | 7fa47408a3 | ||
|   | 3a76248071 | ||
|   | fe501bd7f7 | ||
|   | 27b7ba814a | ||
|   | 9307f57747 | ||
|   | 63bfad0ff4 | ||
|   | f5ef341c9e | ||
|   | 67da18e374 | ||
|   | 468aabd4ef | ||
|   | b2ce0844b6 | ||
|   | b48a22bf50 | ||
|   | 5ff0ae7d48 | ||
|   | 54ec566281 | ||
|   | 17426a60f0 | ||
|   | dade977307 | ||
|   | 6f09edeb91 | ||
|   | b2cfcda114 | ||
|   | b89e6c0fa9 | ||
|   | 1205070687 | ||
|   | eab561bb87 | ||
|   | fbbd2e35cb | ||
|   | 1edca1ee2a | ||
|   | d6928a3c26 | ||
|   | 3c1f393c81 | ||
|   | 65a2b5e219 | ||
|   | 304467feb2 | ||
|   | 186a12ef7f | ||
|   | b648a85841 | ||
|   | f21f1d8ab9 | ||
|   | a7b2327c34 | ||
|   | befeb17f6f | ||
|   | 5eaa0f24e7 | ||
|   | aa20faeaa5 | ||
|   | 6617005365 | ||
|   | b5bed7b0fa | ||
|   | 604811bfc5 | ||
|   | c12db28251 | ||
|   | b0c295e545 | ||
|   | 7355bb7f29 | ||
|   | a226d74133 | ||
|   | 40d2346f29 | ||
|   | 454ecb56e3 | ||
|   | 6f7147376f | ||
|   | 5a460e4ea5 | ||
|   | d05d8f6558 | ||
|   | e20feeeee9 | ||
|   | 4793bfcb7c | ||
|   | d2572f8b33 | ||
|   | 0ede616f31 | ||
|   | befbea2f00 | ||
|   | 60de1506fe | ||
|   | a72a66caa8 | ||
|   | ff88eb588e | ||
|   | 9550ae6984 | ||
|   | 12eddb18fb | ||
|   | ba8071bbef | ||
|   | 8cd1f9a309 | ||
|   | 646280972b | ||
|   | fef2cdabfe | ||
|   | ef69c7969f | ||
|   | 537ff68edd | ||
|   | f02024615a | ||
|   | c79094d7a8 | ||
|   | 7a79131bf2 | ||
|   | 3984c14260 | ||
|   | 4168335619 | ||
|   | 8bdc713352 | ||
|   | 84cd4a3854 | ||
|   | c3c55d82ae | ||
|   | 8aac55cc57 | ||
|   | 3adf082002 | ||
|   | 3d966d8a41 | ||
|   | 83eb7447a1 | ||
|   | 925d2b051c | ||
|   | 3e676bce9e | ||
|   | ef1340bd32 | ||
|   | 2748f83e12 | ||
|   | 894d9b6587 | ||
|   | 9bdf477f2f | ||
|   | fb3f423279 | ||
|   | b1b9c844ac | ||
|   | 3573170dfa | ||
|   | d86506052c | ||
|   | 45665dd3b4 | ||
|   | b52fa96238 | ||
|   | 0ea6d131e0 | ||
|   | 6b05d2be28 | ||
|   | 99cbc20778 | ||
|   | 59c855276b | ||
|   | 4655a5f059 | ||
|   | b3a8754013 | ||
|   | 0511b2a012 | ||
|   | 143f86d60b | ||
|   | 8fa8d0e648 | ||
|   | f31b9987ba | ||
|   | 5c30a60e30 | ||
|   | 471e89a8b7 | ||
|   | 19e0abcb27 | ||
|   | 5597f4e6f2 | ||
|   | c3be82fe6e | ||
|   | a2fb91b8af | ||
| f9637502ee | |||
|   | 58fbf64a27 | ||
|   | 271e104c7e | ||
|   | f1d1ec3d77 | ||
|   | 33b73d887a | ||
|   | 1e7cc72cd8 | ||
|   | 1a59cae743 | ||
|   | 067b04aaf1 | ||
|   | 0ddfe6fcfb | ||
|   | 62f5bdbbd2 | ||
|   | dc57652085 | ||
|   | d0f4554dbe | ||
|   | 785f3c98da | ||
|   | d3f4af4a3a | ||
|   | e58ef418c7 | ||
|   | 802b5aca05 | ||
|   | 84b5ad09e6 | ||
|   | b8f0613b30 | ||
|   | faf9f06e0a | ||
|   | bcaf60015a | ||
|   | 0872051bfa | ||
|   | 05eb16d6de | ||
|   | e43ecad8af | ||
|   | 4094624828 | ||
|   | 70845a2d13 | ||
|   | fbf050167e | ||
|   | 149155ee20 | ||
|   | 29923cc71a | ||
|   | 64cc4fe915 | ||
|   | 4790a3d94b | ||
|   | 356d9e8e19 | ||
|   | dc35ce79e4 | ||
|   | 35a18146a2 | ||
|   | f9b3e3360b | ||
|   | 8cc6fe465c | ||
|   | af84f215f9 | ||
|   | 2327578adc | ||
|   | 9d1af762d5 | ||
|   | fd46c597ae | ||
|   | fdbe9ba149 | ||
|   | 0e82bd024a | ||
|   | 2a92fef879 | ||
|   | 84fd5cd5bb | ||
|   | 0f1acb6cef | ||
|   | 6d4c6924d6 | ||
|   | 4904d7711e | ||
|   | 530145ba3b | ||
|   | 26c2a1ba68 | ||
|   | cb481f36c5 | ||
|   | a72ade9475 | ||
| 5ba0687123 | |||
| fef207bf00 | |||
| 5ef3552549 | |||
| 0f6ca4be21 | |||
| 4653348b13 | |||
| 6826284108 | |||
| c93fdca80d | |||
| 432b6d61a6 | |||
| 4c2b7d7573 | |||
| d8e25a6226 | |||
| db6f4eaab1 | |||
| 4555f18c41 | |||
| 788d8a8b98 | |||
| 55f22f74f5 | |||
| de2f7e857d | |||
| 7c869ab033 | |||
| f9c680ddc0 | |||
| 8efe191897 | |||
| 8d6f1a6128 | |||
| 81bae35d2f | |||
| fc5744c7f0 | |||
| 7aea82d526 | |||
| cb29054e66 | |||
| 0416648b39 | |||
| 01fea69352 | |||
| c7a2133639 | |||
| a162f188c2 | |||
| 2b54804c7b | |||
| a8fef30871 | |||
| 9dc4d903c7 | |||
| b8b18995c5 | |||
| 971b397133 | |||
| aee7dc94bc | |||
| feb8db1212 | |||
| f9f7f005f2 | |||
| 2321a886ae | |||
| 72858c6746 | |||
| 79ca5a3026 | |||
| 3d37998174 | |||
| ce29e40b57 | |||
| ef26d6afdc | |||
| dc84bc9391 | |||
| 321eb18cd7 | |||
| 6936b8c4f3 | |||
| 26f43ee9b8 | |||
| e19d318af9 | |||
| dfc7f764de | |||
| 331b4cc42c | |||
| 674d537f91 | |||
| a442a019d9 | |||
| 774a554405 | |||
| 90f56e07ff | |||
| 4b428ffb8a | |||
| bcd0caecd1 | |||
| 78c32afa4e | |||
| f3302fe1b9 | |||
| 7eba06c43d | |||
| 713f8e2c6a | |||
| ea0100310b | |||
| 4332bfe537 | |||
| 25ce2bdd92 | |||
| dc17ef4f7c | |||
| 8097508909 | |||
| 8addc33734 | |||
| 990136a337 | |||
| d14b204aae | |||
| 4067829d2c | |||
| 8bc4c8c485 | |||
| bf8aec2a14 | |||
| ace2787868 | |||
| 08dde1da13 | |||
| 4cde7a4b06 | |||
| 42ce8a82af | |||
| 6d6e446f6f | |||
| 26bf667fec | |||
| 18b9c9b0b1 | |||
| f78ca8833b | |||
| 19337de8f0 | |||
| c2a4fbc98c | |||
| 87c0e13efd | |||
| 3442097b31 | |||
| c7764ed1d0 | |||
| 6e39022af9 | |||
| d88716feba | |||
| 678347d836 | |||
| 890ccea846 | |||
| 405525357d | |||
| 3eee2a3311 | |||
| 55d1f0081d | |||
| ea73d9bf86 | |||
| 3eab15180c | |||
| 2210be45fe | |||
| 5bdc3dfad8 | |||
| c22440fe30 | |||
| b41844290b | |||
| 32a3440156 | |||
| 630eb3c143 | |||
| 534b628ad2 | |||
| 8a463524b4 | |||
| b50eefbd5b | |||
| 3a2ebeca11 | |||
| 95f7da61a9 | |||
| 0d04beb777 | |||
| 7ab26ff7af | |||
| 6800fc6103 | |||
| 9077c1f24f | |||
| 2327f2af6f | |||
| 41fff9c930 | |||
| cfcef40c65 | |||
| 29d158a3bc | |||
| 411cf324dd | |||
| 52230a803f | |||
| ddf6f275db | |||
| 8c65ee54d0 | |||
| d07d44fcc7 | |||
| 772d59f0ab | |||
| f7da3f88f9 | |||
| e4f6cf9993 | |||
| dd34c93656 | |||
| 320ffa2308 | |||
| b5e7136f68 | |||
| e2b7664451 | |||
| 725ad07e6f | |||
| 75cbd69d85 | |||
| a9a71ef011 | |||
| 362ba36695 | |||
| 38d687ede2 | |||
| 78cd1cf494 | |||
| 0b990d42cd | |||
| 74571de5b6 | |||
| 01ce61f6e2 | |||
| 09c9aa078d | |||
| 73441d690e | |||
| afdc21ee04 | |||
| fc317b7f28 | |||
| b3f2b7faf4 | |||
| 7ea70dcb53 | |||
| d0b90fdef7 | |||
| 3c05d31d2e | |||
| 11f5eb21af | |||
| c90665645e | |||
| fb3c71820b | |||
| e533774ac0 | |||
| 647f8de9bb | |||
| 599bf57cd8 | |||
| 50c506ea2d | |||
| 4cc7990b1a | |||
| 4ef5fdefb2 | |||
| a018837214 | |||
| e74f0e1558 | |||
| fd882b5167 | |||
| 15bda62b89 | |||
| 5e4ce96266 | |||
| dbd2f0d06f | |||
| c87e657412 | |||
| 6275e3f08f | |||
| bc2e4a2452 | |||
| ba7d9fb724 | |||
| c50ab96abb | |||
| fa68c6a0fa | |||
| d1b60fec48 | |||
| 99a839605c | |||
| 08f5b3e920 | |||
| 87e0a26d24 | |||
| 91c07e9f99 | |||
| 9b2b75e4b4 | |||
| 77c913c70a | |||
| 1a1bea527c | |||
| 46f8f6d90d | |||
| dbad3b6489 | |||
| 1821cedbc4 | |||
| 1448eafd64 | |||
| 8f4047b36a | |||
| 2683fde42a | |||
| 02522d877d | |||
| 769ffa2982 | |||
| 33eed14141 | |||
| a0bd47a012 | |||
| 8c14ef97bf | |||
| 5bdfbe8250 | |||
| f2319c9689 | |||
| c3138c6497 | |||
| 56e8308621 | |||
| cb6a8756b6 | |||
| e7242143a0 | |||
| c12898b63a | |||
| 9453f29deb | |||
| 9093816113 | |||
| 3471c1b87e | |||
| 30f0de9427 | |||
| 5278e94566 | |||
| 08b1e9d764 | |||
| 30427e0626 | |||
| 752a5b9bc3 | |||
| a5390d5461 | |||
| a02fa19d5a | |||
| f88bdcd4ff | |||
| b98f8a570c | |||
| 644070340d | |||
| 93fecfe7e9 | |||
| 53bb3ac361 | |||
| 137df8c6d3 | |||
| 9863285bf0 | |||
| a392b4a14f | |||
| d03569e908 | |||
| b1097e9c61 | |||
| 5bda6bf48b | |||
| a03cdacd9e | |||
| c3fe33f5a0 | |||
| 5d823ff1a7 | |||
| 63df9dd1f4 | |||
| 0c80c9fead | |||
| b8d42a7cc6 | |||
| 4e7dc30fea | |||
| 99c68b1091 | |||
| d48979091e | |||
| 785caa5b6c | |||
| 261d7331f4 | |||
| 28bd8409df | |||
| 47008a157c | |||
| fc1e8681ef | |||
| 17085b4379 | |||
| dd6eefcd9c | |||
| ae2b0e63d6 | |||
| bcbae097de | |||
| b59dca4eeb | |||
| 8098798fa9 | |||
| d8d0e2c99f | |||
| 214233f82f | |||
| eebe82c990 | |||
| 5b73071d64 | |||
| cd04de7f72 | |||
| cf4b1317e1 | |||
| 10e353b090 | |||
| 81bd756ec6 | |||
| 9527d8aafd | |||
| e35bc58e0e | |||
| bd0f9fd913 | |||
| 44957f7806 | |||
| 7ff26eb95d | |||
| 1f2471fa67 | |||
| 7a5588a408 | |||
| ac03ae737f | |||
| f9db95f555 | |||
| 2bc045a997 | |||
| 531b0fa529 | |||
| 6b1ed4fb9b | |||
| 645a6a9f54 | |||
| 88cd291b0f | |||
| 76e4aaf429 | |||
| 365f8ad981 | |||
| 0af08f9469 | |||
| 23ce658af7 | |||
| 0a54474f98 | |||
| 93ca9ed3a8 | |||
| d110fdccc2 | |||
| 4197d983bf | |||
| d23883b799 | |||
| 675d2ac374 | |||
| 5c86735ab7 | |||
| 566274dcac | |||
| de2814545b | |||
| 4ea26f22c4 | |||
| 458bc7f921 | |||
| 3839698e4a | |||
| b403863e62 | |||
| 246b73f922 | |||
| 6da7f462a9 | |||
| 90874b8b00 | |||
| 7e874a33fb | |||
| bbe357e5c0 | |||
| 428cdae3cf | |||
| 1c689a6b24 | |||
| 55972ef2c1 | |||
| 966687d1ab | |||
| 6a86144adf | |||
| 57765e88c0 | |||
| 60cddad047 | |||
| a77a33dc50 | |||
| 405a07e638 | |||
| 75f9ce9d77 | |||
| 259588e747 | |||
| 0e8b746fb0 | |||
| 753917c10c | |||
| 39f7364f25 | |||
| 8d7de5fcb6 | |||
| 01398f762b | |||
| e12d2efe81 | |||
| 5c7055d840 | |||
| 562c7aa126 | |||
| 5994088e50 | |||
| 9edbe22e19 | |||
| 7fabfff397 | |||
| 356a2fe0e8 | |||
| 54193ebb15 | |||
| 2b4bb9cddd | |||
| 2758907517 | |||
| a7f641eee2 | |||
| 9799ceff80 | |||
| 26e86c2171 | |||
| f6c293fb4d | |||
| 5abc5cf9f8 | |||
| 41a820fdf0 | |||
| 2c8b09da21 | |||
| a7ff526360 | |||
| 1a8148be97 | |||
| 199dd85140 | |||
| f6c44fdb03 | |||
| 1aade72cb1 | |||
| 121c9d308b | |||
| d60a47ab5b | |||
| 8af9b8796f | |||
| 7dd7673fb3 | |||
| aeaf0902e1 | |||
| 498842475c | |||
| 755177508e | |||
| 5b49fd93e2 | |||
| 968ea35b03 | |||
| 97ed90b82a | |||
| ba34aa535a | |||
| e56041da3b | |||
| b19fbc39af | |||
| 1036d419fa | |||
| 0011789443 | |||
| ff7d71fb87 | 
| @@ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
|   "phabricator.uri": "https://secure.phabricator.com/", |   "phabricator.uri": "https://developer.blender.org/", | ||||||
|   "load": ["src/"], |   "load": ["src/"], | ||||||
|   "history.immutable": false |   "history.immutable": false | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								.arclint
									
									
									
									
									
								
							
							
						
						| @@ -64,13 +64,13 @@ | |||||||
|     "text": { |     "text": { | ||||||
|       "type": "text", |       "type": "text", | ||||||
|       "exclude": [ |       "exclude": [ | ||||||
|         "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json))" |         "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect))" | ||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "text-without-length": { |     "text-without-length": { | ||||||
|       "type": "text", |       "type": "text", | ||||||
|       "include": [ |       "include": [ | ||||||
|         "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json))" |         "(^src/(.*/)?__tests__/[^/]+/.*\\.(txt|json|expect))" | ||||||
|       ], |       ], | ||||||
|       "severity": { |       "severity": { | ||||||
|         "3": "disabled" |         "3": "disabled" | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -40,3 +40,6 @@ | |||||||
| # Places for users to add custom resources. | # Places for users to add custom resources. | ||||||
| /resources/cows/custom/* | /resources/cows/custom/* | ||||||
| /resources/figlet/custom/* | /resources/figlet/custom/* | ||||||
|  |  | ||||||
|  | # blender migration files | ||||||
|  | migration/dump/ | ||||||
|   | |||||||
							
								
								
									
										769
									
								
								externals/cldr/cldr_windows_timezones.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,769 @@ | |||||||
|  | <?xml version="1.0" encoding="UTF-8" ?> | ||||||
|  | <!DOCTYPE supplementalData SYSTEM "../../common/dtd/ldmlSupplemental.dtd"> | ||||||
|  | <!-- | ||||||
|  | Copyright © 1991-2013 Unicode, Inc. | ||||||
|  | CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/) | ||||||
|  | For terms of use, see http://www.unicode.org/copyright.html | ||||||
|  | --> | ||||||
|  |  | ||||||
|  | <supplementalData> | ||||||
|  | 	<version number="$Revision$"/> | ||||||
|  | 	<windowsZones> | ||||||
|  | 		<mapTimezones otherVersion="7e00402" typeVersion="2016i"> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-12:00) International Date Line West --> | ||||||
|  | 			<mapZone other="Dateline Standard Time" territory="001" type="Etc/GMT+12"/> | ||||||
|  | 			<mapZone other="Dateline Standard Time" territory="ZZ" type="Etc/GMT+12"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-11:00) Coordinated Universal Time-11 --> | ||||||
|  | 			<mapZone other="UTC-11" territory="001" type="Etc/GMT+11"/> | ||||||
|  | 			<mapZone other="UTC-11" territory="AS" type="Pacific/Pago_Pago"/> | ||||||
|  | 			<mapZone other="UTC-11" territory="NU" type="Pacific/Niue"/> | ||||||
|  | 			<mapZone other="UTC-11" territory="UM" type="Pacific/Midway"/> | ||||||
|  | 			<mapZone other="UTC-11" territory="ZZ" type="Etc/GMT+11"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-10:00) Aleutian Islands --> | ||||||
|  | 			<mapZone other="Aleutian Standard Time" territory="001" type="America/Adak"/> | ||||||
|  | 			<mapZone other="Aleutian Standard Time" territory="US" type="America/Adak"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-10:00) Hawaii --> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="001" type="Pacific/Honolulu"/> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="CK" type="Pacific/Rarotonga"/> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="PF" type="Pacific/Tahiti"/> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="UM" type="Pacific/Johnston"/> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="US" type="Pacific/Honolulu"/> | ||||||
|  | 			<mapZone other="Hawaiian Standard Time" territory="ZZ" type="Etc/GMT+10"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-09:30) Marquesas Islands --> | ||||||
|  | 			<mapZone other="Marquesas Standard Time" territory="001" type="Pacific/Marquesas"/> | ||||||
|  | 			<mapZone other="Marquesas Standard Time" territory="PF" type="Pacific/Marquesas"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-09:00) Alaska --> | ||||||
|  | 			<mapZone other="Alaskan Standard Time" territory="001" type="America/Anchorage"/> | ||||||
|  | 			<mapZone other="Alaskan Standard Time" territory="US" type="America/Anchorage America/Juneau America/Metlakatla America/Nome America/Sitka America/Yakutat"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-09:00) Coordinated Universal Time-09 --> | ||||||
|  | 			<mapZone other="UTC-09" territory="001" type="Etc/GMT+9"/> | ||||||
|  | 			<mapZone other="UTC-09" territory="PF" type="Pacific/Gambier"/> | ||||||
|  | 			<mapZone other="UTC-09" territory="ZZ" type="Etc/GMT+9"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-08:00) Baja California --> | ||||||
|  | 			<mapZone other="Pacific Standard Time (Mexico)" territory="001" type="America/Tijuana"/> | ||||||
|  | 			<mapZone other="Pacific Standard Time (Mexico)" territory="MX" type="America/Tijuana America/Santa_Isabel"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-08:00) Coordinated Universal Time-08 --> | ||||||
|  | 			<mapZone other="UTC-08" territory="001" type="Etc/GMT+8"/> | ||||||
|  | 			<mapZone other="UTC-08" territory="PN" type="Pacific/Pitcairn"/> | ||||||
|  | 			<mapZone other="UTC-08" territory="ZZ" type="Etc/GMT+8"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-08:00) Pacific Time (US & Canada) --> | ||||||
|  | 			<mapZone other="Pacific Standard Time" territory="001" type="America/Los_Angeles"/> | ||||||
|  | 			<mapZone other="Pacific Standard Time" territory="CA" type="America/Vancouver America/Dawson America/Whitehorse"/> | ||||||
|  | 			<mapZone other="Pacific Standard Time" territory="US" type="America/Los_Angeles"/> | ||||||
|  | 			<mapZone other="Pacific Standard Time" territory="ZZ" type="PST8PDT"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-07:00) Arizona --> | ||||||
|  | 			<mapZone other="US Mountain Standard Time" territory="001" type="America/Phoenix"/> | ||||||
|  | 			<mapZone other="US Mountain Standard Time" territory="CA" type="America/Dawson_Creek America/Creston America/Fort_Nelson"/> | ||||||
|  | 			<mapZone other="US Mountain Standard Time" territory="MX" type="America/Hermosillo"/> | ||||||
|  | 			<mapZone other="US Mountain Standard Time" territory="US" type="America/Phoenix"/> | ||||||
|  | 			<mapZone other="US Mountain Standard Time" territory="ZZ" type="Etc/GMT+7"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-07:00) Chihuahua, La Paz, Mazatlan --> | ||||||
|  | 			<mapZone other="Mountain Standard Time (Mexico)" territory="001" type="America/Chihuahua"/> | ||||||
|  | 			<mapZone other="Mountain Standard Time (Mexico)" territory="MX" type="America/Chihuahua America/Mazatlan"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-07:00) Mountain Time (US & Canada) --> | ||||||
|  | 			<mapZone other="Mountain Standard Time" territory="001" type="America/Denver"/> | ||||||
|  | 			<mapZone other="Mountain Standard Time" territory="CA" type="America/Edmonton America/Cambridge_Bay America/Inuvik America/Yellowknife"/> | ||||||
|  | 			<mapZone other="Mountain Standard Time" territory="MX" type="America/Ojinaga"/> | ||||||
|  | 			<mapZone other="Mountain Standard Time" territory="US" type="America/Denver America/Boise"/> | ||||||
|  | 			<mapZone other="Mountain Standard Time" territory="ZZ" type="MST7MDT"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-06:00) Central America --> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="001" type="America/Guatemala"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="BZ" type="America/Belize"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="CR" type="America/Costa_Rica"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="EC" type="Pacific/Galapagos"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="GT" type="America/Guatemala"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="HN" type="America/Tegucigalpa"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="NI" type="America/Managua"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="SV" type="America/El_Salvador"/> | ||||||
|  | 			<mapZone other="Central America Standard Time" territory="ZZ" type="Etc/GMT+6"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-06:00) Central Time (US & Canada) --> | ||||||
|  | 			<mapZone other="Central Standard Time" territory="001" type="America/Chicago"/> | ||||||
|  | 			<mapZone other="Central Standard Time" territory="CA" type="America/Winnipeg America/Rainy_River America/Rankin_Inlet America/Resolute"/> | ||||||
|  | 			<mapZone other="Central Standard Time" territory="MX" type="America/Matamoros"/> | ||||||
|  | 			<mapZone other="Central Standard Time" territory="US" type="America/Chicago America/Indiana/Knox America/Indiana/Tell_City America/Menominee America/North_Dakota/Beulah America/North_Dakota/Center America/North_Dakota/New_Salem"/> | ||||||
|  | 			<mapZone other="Central Standard Time" territory="ZZ" type="CST6CDT"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-06:00) Easter Island --> | ||||||
|  | 			<mapZone other="Easter Island Standard Time" territory="001" type="Pacific/Easter"/> | ||||||
|  | 			<mapZone other="Easter Island Standard Time" territory="CL" type="Pacific/Easter"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-06:00) Guadalajara, Mexico City, Monterrey --> | ||||||
|  | 			<mapZone other="Central Standard Time (Mexico)" territory="001" type="America/Mexico_City"/> | ||||||
|  | 			<mapZone other="Central Standard Time (Mexico)" territory="MX" type="America/Mexico_City America/Bahia_Banderas America/Merida America/Monterrey"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-06:00) Saskatchewan --> | ||||||
|  | 			<mapZone other="Canada Central Standard Time" territory="001" type="America/Regina"/> | ||||||
|  | 			<mapZone other="Canada Central Standard Time" territory="CA" type="America/Regina America/Swift_Current"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Bogota, Lima, Quito, Rio Branco --> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="001" type="America/Bogota"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="BR" type="America/Rio_Branco America/Eirunepe"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="CA" type="America/Coral_Harbour"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="CO" type="America/Bogota"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="EC" type="America/Guayaquil"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="JM" type="America/Jamaica"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="KY" type="America/Cayman"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="PA" type="America/Panama"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="PE" type="America/Lima"/> | ||||||
|  | 			<mapZone other="SA Pacific Standard Time" territory="ZZ" type="Etc/GMT+5"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Chetumal --> | ||||||
|  | 			<mapZone other="Eastern Standard Time (Mexico)" territory="001" type="America/Cancun"/> | ||||||
|  | 			<mapZone other="Eastern Standard Time (Mexico)" territory="MX" type="America/Cancun"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Eastern Time (US & Canada) --> | ||||||
|  | 			<mapZone other="Eastern Standard Time" territory="001" type="America/New_York"/> | ||||||
|  | 			<mapZone other="Eastern Standard Time" territory="BS" type="America/Nassau"/> | ||||||
|  | 			<mapZone other="Eastern Standard Time" territory="CA" type="America/Toronto America/Iqaluit America/Montreal America/Nipigon America/Pangnirtung America/Thunder_Bay"/> | ||||||
|  | 			<mapZone other="Eastern Standard Time" territory="US" type="America/New_York America/Detroit America/Indiana/Petersburg America/Indiana/Vincennes America/Indiana/Winamac America/Kentucky/Monticello America/Louisville"/> | ||||||
|  | 			<mapZone other="Eastern Standard Time" territory="ZZ" type="EST5EDT"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Haiti --> | ||||||
|  | 			<mapZone other="Haiti Standard Time" territory="001" type="America/Port-au-Prince"/> | ||||||
|  | 			<mapZone other="Haiti Standard Time" territory="HT" type="America/Port-au-Prince"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Havana --> | ||||||
|  | 			<mapZone other="Cuba Standard Time" territory="001" type="America/Havana"/> | ||||||
|  | 			<mapZone other="Cuba Standard Time" territory="CU" type="America/Havana"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-05:00) Indiana (East) --> | ||||||
|  | 			<mapZone other="US Eastern Standard Time" territory="001" type="America/Indianapolis"/> | ||||||
|  | 			<mapZone other="US Eastern Standard Time" territory="US" type="America/Indianapolis America/Indiana/Marengo America/Indiana/Vevay"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Asuncion --> | ||||||
|  | 			<mapZone other="Paraguay Standard Time" territory="001" type="America/Asuncion"/> | ||||||
|  | 			<mapZone other="Paraguay Standard Time" territory="PY" type="America/Asuncion"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Atlantic Time (Canada) --> | ||||||
|  | 			<mapZone other="Atlantic Standard Time" territory="001" type="America/Halifax"/> | ||||||
|  | 			<mapZone other="Atlantic Standard Time" territory="BM" type="Atlantic/Bermuda"/> | ||||||
|  | 			<mapZone other="Atlantic Standard Time" territory="CA" type="America/Halifax America/Glace_Bay America/Goose_Bay America/Moncton"/> | ||||||
|  | 			<mapZone other="Atlantic Standard Time" territory="GL" type="America/Thule"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Caracas --> | ||||||
|  | 			<mapZone other="Venezuela Standard Time" territory="001" type="America/Caracas"/> | ||||||
|  | 			<mapZone other="Venezuela Standard Time" territory="VE" type="America/Caracas"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Cuiaba --> | ||||||
|  | 			<mapZone other="Central Brazilian Standard Time" territory="001" type="America/Cuiaba"/> | ||||||
|  | 			<mapZone other="Central Brazilian Standard Time" territory="BR" type="America/Cuiaba America/Campo_Grande"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Georgetown, La Paz, Manaus, San Juan --> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="001" type="America/La_Paz"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="AG" type="America/Antigua"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="AI" type="America/Anguilla"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="AW" type="America/Aruba"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="BB" type="America/Barbados"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="BL" type="America/St_Barthelemy"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="BO" type="America/La_Paz"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="BQ" type="America/Kralendijk"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="BR" type="America/Manaus America/Boa_Vista America/Porto_Velho"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="CA" type="America/Blanc-Sablon"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="CW" type="America/Curacao"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="DM" type="America/Dominica"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="DO" type="America/Santo_Domingo"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="GD" type="America/Grenada"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="GP" type="America/Guadeloupe"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="GY" type="America/Guyana"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="KN" type="America/St_Kitts"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="LC" type="America/St_Lucia"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="MF" type="America/Marigot"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="MQ" type="America/Martinique"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="MS" type="America/Montserrat"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="PR" type="America/Puerto_Rico"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="SX" type="America/Lower_Princes"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="TT" type="America/Port_of_Spain"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="VC" type="America/St_Vincent"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="VG" type="America/Tortola"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="VI" type="America/St_Thomas"/> | ||||||
|  | 			<mapZone other="SA Western Standard Time" territory="ZZ" type="Etc/GMT+4"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Santiago --> | ||||||
|  | 			<mapZone other="Pacific SA Standard Time" territory="001" type="America/Santiago"/> | ||||||
|  | 			<mapZone other="Pacific SA Standard Time" territory="AQ" type="Antarctica/Palmer"/> | ||||||
|  | 			<mapZone other="Pacific SA Standard Time" territory="CL" type="America/Santiago"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-04:00) Turks and Caicos --> | ||||||
|  | 			<mapZone other="Turks And Caicos Standard Time" territory="001" type="America/Grand_Turk"/> | ||||||
|  | 			<mapZone other="Turks And Caicos Standard Time" territory="TC" type="America/Grand_Turk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:30) Newfoundland --> | ||||||
|  | 			<mapZone other="Newfoundland Standard Time" territory="001" type="America/St_Johns"/> | ||||||
|  | 			<mapZone other="Newfoundland Standard Time" territory="CA" type="America/St_Johns"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Araguaina --> | ||||||
|  | 			<mapZone other="Tocantins Standard Time" territory="001" type="America/Araguaina"/> | ||||||
|  | 			<mapZone other="Tocantins Standard Time" territory="BR" type="America/Araguaina"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Brasilia --> | ||||||
|  | 			<mapZone other="E. South America Standard Time" territory="001" type="America/Sao_Paulo"/> | ||||||
|  | 			<mapZone other="E. South America Standard Time" territory="BR" type="America/Sao_Paulo"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Cayenne, Fortaleza --> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="001" type="America/Cayenne"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="AQ" type="Antarctica/Rothera"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="BR" type="America/Fortaleza America/Belem America/Maceio America/Recife America/Santarem"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="FK" type="Atlantic/Stanley"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="GF" type="America/Cayenne"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="SR" type="America/Paramaribo"/> | ||||||
|  | 			<mapZone other="SA Eastern Standard Time" territory="ZZ" type="Etc/GMT+3"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) City of Buenos Aires --> | ||||||
|  | 			<mapZone other="Argentina Standard Time" territory="001" type="America/Buenos_Aires"/> | ||||||
|  | 			<mapZone other="Argentina Standard Time" territory="AR" type="America/Buenos_Aires America/Argentina/La_Rioja America/Argentina/Rio_Gallegos America/Argentina/Salta America/Argentina/San_Juan America/Argentina/San_Luis America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca America/Cordoba America/Jujuy America/Mendoza"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Greenland --> | ||||||
|  | 			<mapZone other="Greenland Standard Time" territory="001" type="America/Godthab"/> | ||||||
|  | 			<mapZone other="Greenland Standard Time" territory="GL" type="America/Godthab"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Montevideo --> | ||||||
|  | 			<mapZone other="Montevideo Standard Time" territory="001" type="America/Montevideo"/> | ||||||
|  | 			<mapZone other="Montevideo Standard Time" territory="UY" type="America/Montevideo"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Saint Pierre and Miquelon --> | ||||||
|  | 			<mapZone other="Saint Pierre Standard Time" territory="001" type="America/Miquelon"/> | ||||||
|  | 			<mapZone other="Saint Pierre Standard Time" territory="PM" type="America/Miquelon"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-03:00) Salvador --> | ||||||
|  | 			<mapZone other="Bahia Standard Time" territory="001" type="America/Bahia"/> | ||||||
|  | 			<mapZone other="Bahia Standard Time" territory="BR" type="America/Bahia"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-02:00) Coordinated Universal Time-02 --> | ||||||
|  | 			<mapZone other="UTC-02" territory="001" type="Etc/GMT+2"/> | ||||||
|  | 			<mapZone other="UTC-02" territory="BR" type="America/Noronha"/> | ||||||
|  | 			<mapZone other="UTC-02" territory="GS" type="Atlantic/South_Georgia"/> | ||||||
|  | 			<mapZone other="UTC-02" territory="ZZ" type="Etc/GMT+2"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-01:00) Azores --> | ||||||
|  | 			<mapZone other="Azores Standard Time" territory="001" type="Atlantic/Azores"/> | ||||||
|  | 			<mapZone other="Azores Standard Time" territory="GL" type="America/Scoresbysund"/> | ||||||
|  | 			<mapZone other="Azores Standard Time" territory="PT" type="Atlantic/Azores"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC-01:00) Cabo Verde Is. --> | ||||||
|  | 			<mapZone other="Cape Verde Standard Time" territory="001" type="Atlantic/Cape_Verde"/> | ||||||
|  | 			<mapZone other="Cape Verde Standard Time" territory="CV" type="Atlantic/Cape_Verde"/> | ||||||
|  | 			<mapZone other="Cape Verde Standard Time" territory="ZZ" type="Etc/GMT+1"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC) Coordinated Universal Time --> | ||||||
|  | 			<mapZone other="UTC" territory="001" type="Etc/GMT"/> | ||||||
|  | 			<mapZone other="UTC" territory="GL" type="America/Danmarkshavn"/> | ||||||
|  | 			<mapZone other="UTC" territory="ZZ" type="Etc/GMT"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+00:00) Casablanca --> | ||||||
|  | 			<mapZone other="Morocco Standard Time" territory="001" type="Africa/Casablanca"/> | ||||||
|  | 			<mapZone other="Morocco Standard Time" territory="EH" type="Africa/El_Aaiun"/> | ||||||
|  | 			<mapZone other="Morocco Standard Time" territory="MA" type="Africa/Casablanca"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+00:00) Dublin, Edinburgh, Lisbon, London --> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="001" type="Europe/London"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="ES" type="Atlantic/Canary"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="FO" type="Atlantic/Faeroe"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="GB" type="Europe/London"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="GG" type="Europe/Guernsey"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="IE" type="Europe/Dublin"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="IM" type="Europe/Isle_of_Man"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="JE" type="Europe/Jersey"/> | ||||||
|  | 			<mapZone other="GMT Standard Time" territory="PT" type="Europe/Lisbon Atlantic/Madeira"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+00:00) Monrovia, Reykjavik --> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="001" type="Atlantic/Reykjavik"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="BF" type="Africa/Ouagadougou"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="CI" type="Africa/Abidjan"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="GH" type="Africa/Accra"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="GM" type="Africa/Banjul"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="GN" type="Africa/Conakry"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="GW" type="Africa/Bissau"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="IS" type="Atlantic/Reykjavik"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="LR" type="Africa/Monrovia"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="ML" type="Africa/Bamako"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="MR" type="Africa/Nouakchott"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="SH" type="Atlantic/St_Helena"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="SL" type="Africa/Freetown"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="SN" type="Africa/Dakar"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="ST" type="Africa/Sao_Tome"/> | ||||||
|  | 			<mapZone other="Greenwich Standard Time" territory="TG" type="Africa/Lome"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna --> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="001" type="Europe/Berlin"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="AD" type="Europe/Andorra"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="AT" type="Europe/Vienna"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="CH" type="Europe/Zurich"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="DE" type="Europe/Berlin Europe/Busingen"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="GI" type="Europe/Gibraltar"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="IT" type="Europe/Rome"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="LI" type="Europe/Vaduz"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="LU" type="Europe/Luxembourg"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="MC" type="Europe/Monaco"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="MT" type="Europe/Malta"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="NL" type="Europe/Amsterdam"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="NO" type="Europe/Oslo"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="SE" type="Europe/Stockholm"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="SJ" type="Arctic/Longyearbyen"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="SM" type="Europe/San_Marino"/> | ||||||
|  | 			<mapZone other="W. Europe Standard Time" territory="VA" type="Europe/Vatican"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague --> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="001" type="Europe/Budapest"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="AL" type="Europe/Tirane"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="CZ" type="Europe/Prague"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="HU" type="Europe/Budapest"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="ME" type="Europe/Podgorica"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="RS" type="Europe/Belgrade"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="SI" type="Europe/Ljubljana"/> | ||||||
|  | 			<mapZone other="Central Europe Standard Time" territory="SK" type="Europe/Bratislava"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) Brussels, Copenhagen, Madrid, Paris --> | ||||||
|  | 			<mapZone other="Romance Standard Time" territory="001" type="Europe/Paris"/> | ||||||
|  | 			<mapZone other="Romance Standard Time" territory="BE" type="Europe/Brussels"/> | ||||||
|  | 			<mapZone other="Romance Standard Time" territory="DK" type="Europe/Copenhagen"/> | ||||||
|  | 			<mapZone other="Romance Standard Time" territory="ES" type="Europe/Madrid Africa/Ceuta"/> | ||||||
|  | 			<mapZone other="Romance Standard Time" territory="FR" type="Europe/Paris"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb --> | ||||||
|  | 			<mapZone other="Central European Standard Time" territory="001" type="Europe/Warsaw"/> | ||||||
|  | 			<mapZone other="Central European Standard Time" territory="BA" type="Europe/Sarajevo"/> | ||||||
|  | 			<mapZone other="Central European Standard Time" territory="HR" type="Europe/Zagreb"/> | ||||||
|  | 			<mapZone other="Central European Standard Time" territory="MK" type="Europe/Skopje"/> | ||||||
|  | 			<mapZone other="Central European Standard Time" territory="PL" type="Europe/Warsaw"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) West Central Africa --> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="001" type="Africa/Lagos"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="AO" type="Africa/Luanda"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="BJ" type="Africa/Porto-Novo"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="CD" type="Africa/Kinshasa"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="CF" type="Africa/Bangui"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="CG" type="Africa/Brazzaville"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="CM" type="Africa/Douala"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="DZ" type="Africa/Algiers"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="GA" type="Africa/Libreville"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="GQ" type="Africa/Malabo"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="NE" type="Africa/Niamey"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="NG" type="Africa/Lagos"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="TD" type="Africa/Ndjamena"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="TN" type="Africa/Tunis"/> | ||||||
|  | 			<mapZone other="W. Central Africa Standard Time" territory="ZZ" type="Etc/GMT-1"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+01:00) Windhoek --> | ||||||
|  | 			<mapZone other="Namibia Standard Time" territory="001" type="Africa/Windhoek"/> | ||||||
|  | 			<mapZone other="Namibia Standard Time" territory="NA" type="Africa/Windhoek"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Amman --> | ||||||
|  | 			<mapZone other="Jordan Standard Time" territory="001" type="Asia/Amman"/> | ||||||
|  | 			<mapZone other="Jordan Standard Time" territory="JO" type="Asia/Amman"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Athens, Bucharest --> | ||||||
|  | 			<mapZone other="GTB Standard Time" territory="001" type="Europe/Bucharest"/> | ||||||
|  | 			<mapZone other="GTB Standard Time" territory="CY" type="Asia/Nicosia"/> | ||||||
|  | 			<mapZone other="GTB Standard Time" territory="GR" type="Europe/Athens"/> | ||||||
|  | 			<mapZone other="GTB Standard Time" territory="RO" type="Europe/Bucharest"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Beirut --> | ||||||
|  | 			<mapZone other="Middle East Standard Time" territory="001" type="Asia/Beirut"/> | ||||||
|  | 			<mapZone other="Middle East Standard Time" territory="LB" type="Asia/Beirut"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Cairo --> | ||||||
|  | 			<mapZone other="Egypt Standard Time" territory="001" type="Africa/Cairo"/> | ||||||
|  | 			<mapZone other="Egypt Standard Time" territory="EG" type="Africa/Cairo"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Chisinau --> | ||||||
|  | 			<mapZone other="E. Europe Standard Time" territory="001" type="Europe/Chisinau"/> | ||||||
|  | 			<mapZone other="E. Europe Standard Time" territory="MD" type="Europe/Chisinau"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Damascus --> | ||||||
|  | 			<mapZone other="Syria Standard Time" territory="001" type="Asia/Damascus"/> | ||||||
|  | 			<mapZone other="Syria Standard Time" territory="SY" type="Asia/Damascus"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Gaza, Hebron --> | ||||||
|  | 			<mapZone other="West Bank Standard Time" territory="001" type="Asia/Hebron"/> | ||||||
|  | 			<mapZone other="West Bank Standard Time" territory="PS" type="Asia/Hebron Asia/Gaza"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Harare, Pretoria --> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="001" type="Africa/Johannesburg"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="BI" type="Africa/Bujumbura"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="BW" type="Africa/Gaborone"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="CD" type="Africa/Lubumbashi"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="LS" type="Africa/Maseru"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="MW" type="Africa/Blantyre"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="MZ" type="Africa/Maputo"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="RW" type="Africa/Kigali"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="SZ" type="Africa/Mbabane"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="ZA" type="Africa/Johannesburg"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="ZM" type="Africa/Lusaka"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="ZW" type="Africa/Harare"/> | ||||||
|  | 			<mapZone other="South Africa Standard Time" territory="ZZ" type="Etc/GMT-2"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius --> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="001" type="Europe/Kiev"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="AX" type="Europe/Mariehamn"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="BG" type="Europe/Sofia"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="EE" type="Europe/Tallinn"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="FI" type="Europe/Helsinki"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="LT" type="Europe/Vilnius"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="LV" type="Europe/Riga"/> | ||||||
|  | 			<mapZone other="FLE Standard Time" territory="UA" type="Europe/Kiev Europe/Uzhgorod Europe/Zaporozhye"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Istanbul --> | ||||||
|  | 			<mapZone other="Turkey Standard Time" territory="001" type="Europe/Istanbul"/> | ||||||
|  | 			<mapZone other="Turkey Standard Time" territory="TR" type="Europe/Istanbul"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Jerusalem --> | ||||||
|  | 			<mapZone other="Israel Standard Time" territory="001" type="Asia/Jerusalem"/> | ||||||
|  | 			<mapZone other="Israel Standard Time" territory="IL" type="Asia/Jerusalem"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Kaliningrad --> | ||||||
|  | 			<mapZone other="Kaliningrad Standard Time" territory="001" type="Europe/Kaliningrad"/> | ||||||
|  | 			<mapZone other="Kaliningrad Standard Time" territory="RU" type="Europe/Kaliningrad"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+02:00) Tripoli --> | ||||||
|  | 			<mapZone other="Libya Standard Time" territory="001" type="Africa/Tripoli"/> | ||||||
|  | 			<mapZone other="Libya Standard Time" territory="LY" type="Africa/Tripoli"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:00) Baghdad --> | ||||||
|  | 			<mapZone other="Arabic Standard Time" territory="001" type="Asia/Baghdad"/> | ||||||
|  | 			<mapZone other="Arabic Standard Time" territory="IQ" type="Asia/Baghdad"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:00) Kuwait, Riyadh --> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="001" type="Asia/Riyadh"/> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="BH" type="Asia/Bahrain"/> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="KW" type="Asia/Kuwait"/> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="QA" type="Asia/Qatar"/> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="SA" type="Asia/Riyadh"/> | ||||||
|  | 			<mapZone other="Arab Standard Time" territory="YE" type="Asia/Aden"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:00) Minsk --> | ||||||
|  | 			<mapZone other="Belarus Standard Time" territory="001" type="Europe/Minsk"/> | ||||||
|  | 			<mapZone other="Belarus Standard Time" territory="BY" type="Europe/Minsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:00) Moscow, St. Petersburg, Volgograd --> | ||||||
|  | 			<mapZone other="Russian Standard Time" territory="001" type="Europe/Moscow"/> | ||||||
|  | 			<mapZone other="Russian Standard Time" territory="RU" type="Europe/Moscow Europe/Kirov Europe/Volgograd"/> | ||||||
|  | 			<mapZone other="Russian Standard Time" territory="UA" type="Europe/Simferopol"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:00) Nairobi --> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="001" type="Africa/Nairobi"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="AQ" type="Antarctica/Syowa"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="DJ" type="Africa/Djibouti"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="ER" type="Africa/Asmera"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="ET" type="Africa/Addis_Ababa"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="KE" type="Africa/Nairobi"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="KM" type="Indian/Comoro"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="MG" type="Indian/Antananarivo"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="SD" type="Africa/Khartoum"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="SO" type="Africa/Mogadishu"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="SS" type="Africa/Juba"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="TZ" type="Africa/Dar_es_Salaam"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="UG" type="Africa/Kampala"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="YT" type="Indian/Mayotte"/> | ||||||
|  | 			<mapZone other="E. Africa Standard Time" territory="ZZ" type="Etc/GMT-3"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+03:30) Tehran --> | ||||||
|  | 			<mapZone other="Iran Standard Time" territory="001" type="Asia/Tehran"/> | ||||||
|  | 			<mapZone other="Iran Standard Time" territory="IR" type="Asia/Tehran"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Abu Dhabi, Muscat --> | ||||||
|  | 			<mapZone other="Arabian Standard Time" territory="001" type="Asia/Dubai"/> | ||||||
|  | 			<mapZone other="Arabian Standard Time" territory="AE" type="Asia/Dubai"/> | ||||||
|  | 			<mapZone other="Arabian Standard Time" territory="OM" type="Asia/Muscat"/> | ||||||
|  | 			<mapZone other="Arabian Standard Time" territory="ZZ" type="Etc/GMT-4"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Astrakhan, Ulyanovsk --> | ||||||
|  | 			<mapZone other="Astrakhan Standard Time" territory="001" type="Europe/Astrakhan"/> | ||||||
|  | 			<mapZone other="Astrakhan Standard Time" territory="RU" type="Europe/Astrakhan Europe/Ulyanovsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Baku --> | ||||||
|  | 			<mapZone other="Azerbaijan Standard Time" territory="001" type="Asia/Baku"/> | ||||||
|  | 			<mapZone other="Azerbaijan Standard Time" territory="AZ" type="Asia/Baku"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Izhevsk, Samara --> | ||||||
|  | 			<mapZone other="Russia Time Zone 3" territory="001" type="Europe/Samara"/> | ||||||
|  | 			<mapZone other="Russia Time Zone 3" territory="RU" type="Europe/Samara"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Port Louis --> | ||||||
|  | 			<mapZone other="Mauritius Standard Time" territory="001" type="Indian/Mauritius"/> | ||||||
|  | 			<mapZone other="Mauritius Standard Time" territory="MU" type="Indian/Mauritius"/> | ||||||
|  | 			<mapZone other="Mauritius Standard Time" territory="RE" type="Indian/Reunion"/> | ||||||
|  | 			<mapZone other="Mauritius Standard Time" territory="SC" type="Indian/Mahe"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Tbilisi --> | ||||||
|  | 			<mapZone other="Georgian Standard Time" territory="001" type="Asia/Tbilisi"/> | ||||||
|  | 			<mapZone other="Georgian Standard Time" territory="GE" type="Asia/Tbilisi"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:00) Yerevan --> | ||||||
|  | 			<mapZone other="Caucasus Standard Time" territory="001" type="Asia/Yerevan"/> | ||||||
|  | 			<mapZone other="Caucasus Standard Time" territory="AM" type="Asia/Yerevan"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+04:30) Kabul --> | ||||||
|  | 			<mapZone other="Afghanistan Standard Time" territory="001" type="Asia/Kabul"/> | ||||||
|  | 			<mapZone other="Afghanistan Standard Time" territory="AF" type="Asia/Kabul"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:00) Ashgabat, Tashkent --> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="001" type="Asia/Tashkent"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="AQ" type="Antarctica/Mawson"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="KZ" type="Asia/Oral Asia/Aqtau Asia/Aqtobe"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="MV" type="Indian/Maldives"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="TF" type="Indian/Kerguelen"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="TJ" type="Asia/Dushanbe"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="TM" type="Asia/Ashgabat"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="UZ" type="Asia/Tashkent Asia/Samarkand"/> | ||||||
|  | 			<mapZone other="West Asia Standard Time" territory="ZZ" type="Etc/GMT-5"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:00) Ekaterinburg --> | ||||||
|  | 			<mapZone other="Ekaterinburg Standard Time" territory="001" type="Asia/Yekaterinburg"/> | ||||||
|  | 			<mapZone other="Ekaterinburg Standard Time" territory="RU" type="Asia/Yekaterinburg"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:00) Islamabad, Karachi --> | ||||||
|  | 			<mapZone other="Pakistan Standard Time" territory="001" type="Asia/Karachi"/> | ||||||
|  | 			<mapZone other="Pakistan Standard Time" territory="PK" type="Asia/Karachi"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi --> | ||||||
|  | 			<mapZone other="India Standard Time" territory="001" type="Asia/Calcutta"/> | ||||||
|  | 			<mapZone other="India Standard Time" territory="IN" type="Asia/Calcutta"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:30) Sri Jayawardenepura --> | ||||||
|  | 			<mapZone other="Sri Lanka Standard Time" territory="001" type="Asia/Colombo"/> | ||||||
|  | 			<mapZone other="Sri Lanka Standard Time" territory="LK" type="Asia/Colombo"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+05:45) Kathmandu --> | ||||||
|  | 			<mapZone other="Nepal Standard Time" territory="001" type="Asia/Katmandu"/> | ||||||
|  | 			<mapZone other="Nepal Standard Time" territory="NP" type="Asia/Katmandu"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+06:00) Astana --> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="001" type="Asia/Almaty"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="AQ" type="Antarctica/Vostok"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="CN" type="Asia/Urumqi"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="IO" type="Indian/Chagos"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="KG" type="Asia/Bishkek"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="KZ" type="Asia/Almaty Asia/Qyzylorda"/> | ||||||
|  | 			<mapZone other="Central Asia Standard Time" territory="ZZ" type="Etc/GMT-6"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+06:00) Dhaka --> | ||||||
|  | 			<mapZone other="Bangladesh Standard Time" territory="001" type="Asia/Dhaka"/> | ||||||
|  | 			<mapZone other="Bangladesh Standard Time" territory="BD" type="Asia/Dhaka"/> | ||||||
|  | 			<mapZone other="Bangladesh Standard Time" territory="BT" type="Asia/Thimphu"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+06:00) Omsk --> | ||||||
|  | 			<mapZone other="Omsk Standard Time" territory="001" type="Asia/Omsk"/> | ||||||
|  | 			<mapZone other="Omsk Standard Time" territory="RU" type="Asia/Omsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+06:30) Yangon (Rangoon) --> | ||||||
|  | 			<mapZone other="Myanmar Standard Time" territory="001" type="Asia/Rangoon"/> | ||||||
|  | 			<mapZone other="Myanmar Standard Time" territory="CC" type="Indian/Cocos"/> | ||||||
|  | 			<mapZone other="Myanmar Standard Time" territory="MM" type="Asia/Rangoon"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Bangkok, Hanoi, Jakarta --> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="001" type="Asia/Bangkok"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="AQ" type="Antarctica/Davis"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="CX" type="Indian/Christmas"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="ID" type="Asia/Jakarta Asia/Pontianak"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="KH" type="Asia/Phnom_Penh"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="LA" type="Asia/Vientiane"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="TH" type="Asia/Bangkok"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="VN" type="Asia/Saigon"/> | ||||||
|  | 			<mapZone other="SE Asia Standard Time" territory="ZZ" type="Etc/GMT-7"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Barnaul, Gorno-Altaysk --> | ||||||
|  | 			<mapZone other="Altai Standard Time" territory="001" type="Asia/Barnaul"/> | ||||||
|  | 			<mapZone other="Altai Standard Time" territory="RU" type="Asia/Barnaul"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Hovd --> | ||||||
|  | 			<mapZone other="W. Mongolia Standard Time" territory="001" type="Asia/Hovd"/> | ||||||
|  | 			<mapZone other="W. Mongolia Standard Time" territory="MN" type="Asia/Hovd"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Krasnoyarsk --> | ||||||
|  | 			<mapZone other="North Asia Standard Time" territory="001" type="Asia/Krasnoyarsk"/> | ||||||
|  | 			<mapZone other="North Asia Standard Time" territory="RU" type="Asia/Krasnoyarsk Asia/Novokuznetsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Novosibirsk --> | ||||||
|  | 			<mapZone other="N. Central Asia Standard Time" territory="001" type="Asia/Novosibirsk"/> | ||||||
|  | 			<mapZone other="N. Central Asia Standard Time" territory="RU" type="Asia/Novosibirsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+07:00) Tomsk --> | ||||||
|  | 			<mapZone other="Tomsk Standard Time" territory="001" type="Asia/Tomsk"/> | ||||||
|  | 			<mapZone other="Tomsk Standard Time" territory="RU" type="Asia/Tomsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi --> | ||||||
|  | 			<mapZone other="China Standard Time" territory="001" type="Asia/Shanghai"/> | ||||||
|  | 			<mapZone other="China Standard Time" territory="CN" type="Asia/Shanghai"/> | ||||||
|  | 			<mapZone other="China Standard Time" territory="HK" type="Asia/Hong_Kong"/> | ||||||
|  | 			<mapZone other="China Standard Time" territory="MO" type="Asia/Macau"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Irkutsk --> | ||||||
|  | 			<mapZone other="North Asia East Standard Time" territory="001" type="Asia/Irkutsk"/> | ||||||
|  | 			<mapZone other="North Asia East Standard Time" territory="RU" type="Asia/Irkutsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Kuala Lumpur, Singapore --> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="001" type="Asia/Singapore"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="BN" type="Asia/Brunei"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="ID" type="Asia/Makassar"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="MY" type="Asia/Kuala_Lumpur Asia/Kuching"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="PH" type="Asia/Manila"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="SG" type="Asia/Singapore"/> | ||||||
|  | 			<mapZone other="Singapore Standard Time" territory="ZZ" type="Etc/GMT-8"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Perth --> | ||||||
|  | 			<mapZone other="W. Australia Standard Time" territory="001" type="Australia/Perth"/> | ||||||
|  | 			<mapZone other="W. Australia Standard Time" territory="AU" type="Australia/Perth"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Taipei --> | ||||||
|  | 			<mapZone other="Taipei Standard Time" territory="001" type="Asia/Taipei"/> | ||||||
|  | 			<mapZone other="Taipei Standard Time" territory="TW" type="Asia/Taipei"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:00) Ulaanbaatar --> | ||||||
|  | 			<mapZone other="Ulaanbaatar Standard Time" territory="001" type="Asia/Ulaanbaatar"/> | ||||||
|  | 			<mapZone other="Ulaanbaatar Standard Time" territory="MN" type="Asia/Ulaanbaatar Asia/Choibalsan"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:30) Pyongyang --> | ||||||
|  | 			<mapZone other="North Korea Standard Time" territory="001" type="Asia/Pyongyang"/> | ||||||
|  | 			<mapZone other="North Korea Standard Time" territory="KP" type="Asia/Pyongyang"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+08:45) Eucla --> | ||||||
|  | 			<mapZone other="Aus Central W. Standard Time" territory="001" type="Australia/Eucla"/> | ||||||
|  | 			<mapZone other="Aus Central W. Standard Time" territory="AU" type="Australia/Eucla"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:00) Chita --> | ||||||
|  | 			<mapZone other="Transbaikal Standard Time" territory="001" type="Asia/Chita"/> | ||||||
|  | 			<mapZone other="Transbaikal Standard Time" territory="RU" type="Asia/Chita"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:00) Osaka, Sapporo, Tokyo --> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="001" type="Asia/Tokyo"/> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="ID" type="Asia/Jayapura"/> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="JP" type="Asia/Tokyo"/> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="PW" type="Pacific/Palau"/> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="TL" type="Asia/Dili"/> | ||||||
|  | 			<mapZone other="Tokyo Standard Time" territory="ZZ" type="Etc/GMT-9"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:00) Seoul --> | ||||||
|  | 			<mapZone other="Korea Standard Time" territory="001" type="Asia/Seoul"/> | ||||||
|  | 			<mapZone other="Korea Standard Time" territory="KR" type="Asia/Seoul"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:00) Yakutsk --> | ||||||
|  | 			<mapZone other="Yakutsk Standard Time" territory="001" type="Asia/Yakutsk"/> | ||||||
|  | 			<mapZone other="Yakutsk Standard Time" territory="RU" type="Asia/Yakutsk Asia/Khandyga"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:30) Adelaide --> | ||||||
|  | 			<mapZone other="Cen. Australia Standard Time" territory="001" type="Australia/Adelaide"/> | ||||||
|  | 			<mapZone other="Cen. Australia Standard Time" territory="AU" type="Australia/Adelaide Australia/Broken_Hill"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+09:30) Darwin --> | ||||||
|  | 			<mapZone other="AUS Central Standard Time" territory="001" type="Australia/Darwin"/> | ||||||
|  | 			<mapZone other="AUS Central Standard Time" territory="AU" type="Australia/Darwin"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:00) Brisbane --> | ||||||
|  | 			<mapZone other="E. Australia Standard Time" territory="001" type="Australia/Brisbane"/> | ||||||
|  | 			<mapZone other="E. Australia Standard Time" territory="AU" type="Australia/Brisbane Australia/Lindeman"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:00) Canberra, Melbourne, Sydney --> | ||||||
|  | 			<mapZone other="AUS Eastern Standard Time" territory="001" type="Australia/Sydney"/> | ||||||
|  | 			<mapZone other="AUS Eastern Standard Time" territory="AU" type="Australia/Sydney Australia/Melbourne"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:00) Guam, Port Moresby --> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="001" type="Pacific/Port_Moresby"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="AQ" type="Antarctica/DumontDUrville"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="FM" type="Pacific/Truk"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="GU" type="Pacific/Guam"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="MP" type="Pacific/Saipan"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="PG" type="Pacific/Port_Moresby"/> | ||||||
|  | 			<mapZone other="West Pacific Standard Time" territory="ZZ" type="Etc/GMT-10"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:00) Hobart --> | ||||||
|  | 			<mapZone other="Tasmania Standard Time" territory="001" type="Australia/Hobart"/> | ||||||
|  | 			<mapZone other="Tasmania Standard Time" territory="AU" type="Australia/Hobart Australia/Currie"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:00) Vladivostok --> | ||||||
|  | 			<mapZone other="Vladivostok Standard Time" territory="001" type="Asia/Vladivostok"/> | ||||||
|  | 			<mapZone other="Vladivostok Standard Time" territory="RU" type="Asia/Vladivostok Asia/Ust-Nera"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+10:30) Lord Howe Island --> | ||||||
|  | 			<mapZone other="Lord Howe Standard Time" territory="001" type="Australia/Lord_Howe"/> | ||||||
|  | 			<mapZone other="Lord Howe Standard Time" territory="AU" type="Australia/Lord_Howe"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Bougainville Island --> | ||||||
|  | 			<mapZone other="Bougainville Standard Time" territory="001" type="Pacific/Bougainville"/> | ||||||
|  | 			<mapZone other="Bougainville Standard Time" territory="PG" type="Pacific/Bougainville"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Chokurdakh --> | ||||||
|  | 			<mapZone other="Russia Time Zone 10" territory="001" type="Asia/Srednekolymsk"/> | ||||||
|  | 			<mapZone other="Russia Time Zone 10" territory="RU" type="Asia/Srednekolymsk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Magadan --> | ||||||
|  | 			<mapZone other="Magadan Standard Time" territory="001" type="Asia/Magadan"/> | ||||||
|  | 			<mapZone other="Magadan Standard Time" territory="RU" type="Asia/Magadan"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Norfolk Island --> | ||||||
|  | 			<mapZone other="Norfolk Standard Time" territory="001" type="Pacific/Norfolk"/> | ||||||
|  | 			<mapZone other="Norfolk Standard Time" territory="NF" type="Pacific/Norfolk"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Sakhalin --> | ||||||
|  | 			<mapZone other="Sakhalin Standard Time" territory="001" type="Asia/Sakhalin"/> | ||||||
|  | 			<mapZone other="Sakhalin Standard Time" territory="RU" type="Asia/Sakhalin"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+11:00) Solomon Is., New Caledonia --> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="001" type="Pacific/Guadalcanal"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="AQ" type="Antarctica/Casey"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="AU" type="Antarctica/Macquarie"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="FM" type="Pacific/Ponape Pacific/Kosrae"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="NC" type="Pacific/Noumea"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="SB" type="Pacific/Guadalcanal"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="VU" type="Pacific/Efate"/> | ||||||
|  | 			<mapZone other="Central Pacific Standard Time" territory="ZZ" type="Etc/GMT-11"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky --> | ||||||
|  | 			<mapZone other="Russia Time Zone 11" territory="001" type="Asia/Kamchatka"/> | ||||||
|  | 			<mapZone other="Russia Time Zone 11" territory="RU" type="Asia/Kamchatka Asia/Anadyr"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+12:00) Auckland, Wellington --> | ||||||
|  | 			<mapZone other="New Zealand Standard Time" territory="001" type="Pacific/Auckland"/> | ||||||
|  | 			<mapZone other="New Zealand Standard Time" territory="AQ" type="Antarctica/McMurdo"/> | ||||||
|  | 			<mapZone other="New Zealand Standard Time" territory="NZ" type="Pacific/Auckland"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+12:00) Coordinated Universal Time+12 --> | ||||||
|  | 			<mapZone other="UTC+12" territory="001" type="Etc/GMT-12"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="KI" type="Pacific/Tarawa"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="MH" type="Pacific/Majuro Pacific/Kwajalein"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="NR" type="Pacific/Nauru"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="TV" type="Pacific/Funafuti"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="UM" type="Pacific/Wake"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="WF" type="Pacific/Wallis"/> | ||||||
|  | 			<mapZone other="UTC+12" territory="ZZ" type="Etc/GMT-12"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+12:00) Fiji --> | ||||||
|  | 			<mapZone other="Fiji Standard Time" territory="001" type="Pacific/Fiji"/> | ||||||
|  | 			<mapZone other="Fiji Standard Time" territory="FJ" type="Pacific/Fiji"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+12:45) Chatham Islands --> | ||||||
|  | 			<mapZone other="Chatham Islands Standard Time" territory="001" type="Pacific/Chatham"/> | ||||||
|  | 			<mapZone other="Chatham Islands Standard Time" territory="NZ" type="Pacific/Chatham"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+13:00) Nuku'alofa --> | ||||||
|  | 			<mapZone other="Tonga Standard Time" territory="001" type="Pacific/Tongatapu"/> | ||||||
|  | 			<mapZone other="Tonga Standard Time" territory="KI" type="Pacific/Enderbury"/> | ||||||
|  | 			<mapZone other="Tonga Standard Time" territory="TK" type="Pacific/Fakaofo"/> | ||||||
|  | 			<mapZone other="Tonga Standard Time" territory="TO" type="Pacific/Tongatapu"/> | ||||||
|  | 			<mapZone other="Tonga Standard Time" territory="ZZ" type="Etc/GMT-13"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+13:00) Samoa --> | ||||||
|  | 			<mapZone other="Samoa Standard Time" territory="001" type="Pacific/Apia"/> | ||||||
|  | 			<mapZone other="Samoa Standard Time" territory="WS" type="Pacific/Apia"/> | ||||||
|  |  | ||||||
|  | 			<!-- (UTC+14:00) Kiritimati Island --> | ||||||
|  | 			<mapZone other="Line Islands Standard Time" territory="001" type="Pacific/Kiritimati"/> | ||||||
|  | 			<mapZone other="Line Islands Standard Time" territory="KI" type="Pacific/Kiritimati"/> | ||||||
|  | 			<mapZone other="Line Islands Standard Time" territory="ZZ" type="Etc/GMT-14"/> | ||||||
|  | 		</mapTimezones> | ||||||
|  | 	</windowsZones> | ||||||
|  | </supplementalData> | ||||||
							
								
								
									
										2
									
								
								externals/phpmailer/class.phpmailer.php
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1110,8 +1110,6 @@ class PHPMailer { | |||||||
|  |  | ||||||
|     if($this->MessageID != '') { |     if($this->MessageID != '') { | ||||||
|       $result .= $this->HeaderLine('Message-ID',$this->MessageID); |       $result .= $this->HeaderLine('Message-ID',$this->MessageID); | ||||||
|     } else { |  | ||||||
|       $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); |  | ||||||
|     } |     } | ||||||
|     $result .= $this->HeaderLine('X-Priority', $this->Priority); |     $result .= $this->HeaderLine('X-Priority', $this->Priority); | ||||||
|     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)'); |     $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)'); | ||||||
|   | |||||||
							
								
								
									
										610
									
								
								migration/dedup.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,610 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $migrate_dedup_users = array(); | ||||||
|  |  | ||||||
|  | $migrate_dedup_users["midiclub"] = "midclub"; | ||||||
|  | $migrate_dedup_users["trip"] = "car"; | ||||||
|  | $migrate_dedup_users["thunderbolt"] = "thunderbolt16"; | ||||||
|  | $migrate_dedup_users["avirnig"] = "beav"; | ||||||
|  | $migrate_dedup_users["jeaninmontreal"] = "jeanm"; | ||||||
|  | $migrate_dedup_users["nneo"] = "nneonneo"; | ||||||
|  | $migrate_dedup_users["ebonyj"] = "jim"; | ||||||
|  | $migrate_dedup_users["tnr"] = "ichem"; | ||||||
|  | $migrate_dedup_users["archus"] = "rstehwien"; | ||||||
|  | $migrate_dedup_users["kalysto"] = "kalar"; | ||||||
|  | $migrate_dedup_users["eloe"] = "mouvanteloe"; | ||||||
|  | $migrate_dedup_users["erdling"] = "eitj"; | ||||||
|  | $migrate_dedup_users["cwinebrinner"] = "chuck_1027"; | ||||||
|  | $migrate_dedup_users["foo"] = "mfranz"; | ||||||
|  | $migrate_dedup_users["f00fbug"] = "viviowns"; | ||||||
|  | $migrate_dedup_users["olavbalm"] = "olav"; | ||||||
|  | $migrate_dedup_users["kapong"] = "el_kapong"; | ||||||
|  | $migrate_dedup_users["thorax"] = "rofthorax"; | ||||||
|  | $migrate_dedup_users["kramer3d"] = "asdfghytrewq"; | ||||||
|  | $migrate_dedup_users["reevee"] = "vee"; | ||||||
|  | $migrate_dedup_users["matzeb"] = "matzebraun"; | ||||||
|  | $migrate_dedup_users["jmsoler"] = "jms"; | ||||||
|  | $migrate_dedup_users["aqa"] = "angelito"; | ||||||
|  | $migrate_dedup_users["blendorphin"] = "blenergetic"; | ||||||
|  | $migrate_dedup_users["paolo"] = "jody"; | ||||||
|  | $migrate_dedup_users["blendedidea"] = "chubango"; | ||||||
|  | $migrate_dedup_users["ruiramos"] = "p3ctu5"; | ||||||
|  | $migrate_dedup_users["head_chees"] = "vassilizaitsaf"; | ||||||
|  | $migrate_dedup_users["kiernan"] = "rofthorax"; | ||||||
|  | $migrate_dedup_users["olaf_arnold"] = "olafarnold"; | ||||||
|  | $migrate_dedup_users["joseyanesaltos"] = "joseyanes"; | ||||||
|  | $migrate_dedup_users["nicholasfrancis"] = "nicholas"; | ||||||
|  | $migrate_dedup_users["briancary"] = "brinux"; | ||||||
|  | $migrate_dedup_users["piotrek"] = "ccpiotr"; | ||||||
|  | $migrate_dedup_users["slashdev"] = "colonel_panic"; | ||||||
|  | $migrate_dedup_users["rj2004"] = "rjblender"; | ||||||
|  | $migrate_dedup_users["jeffreymcgrew"] = "toast"; | ||||||
|  | $migrate_dedup_users["hendersj"] = "jhenderson"; | ||||||
|  | $migrate_dedup_users["pierpy"] = "pier"; | ||||||
|  | $migrate_dedup_users["buschhardt"] = "ishtar"; | ||||||
|  | $migrate_dedup_users["timlesher"] = "tim"; | ||||||
|  | $migrate_dedup_users["tizmo"] = "timlucas"; | ||||||
|  | $migrate_dedup_users["pprandin"] = "pashaweb"; | ||||||
|  | $migrate_dedup_users["servivo"] = "taz"; | ||||||
|  | $migrate_dedup_users["stabby"] = "xingo"; | ||||||
|  | $migrate_dedup_users["jimmydietulpe"] = "jimmadietulpe"; | ||||||
|  | $migrate_dedup_users["palmnet"] = "palmer"; | ||||||
|  | $migrate_dedup_users["graphique-chti"] = "gcprod"; | ||||||
|  | $migrate_dedup_users["dreamkatana1"] = "dreamkatana"; | ||||||
|  | $migrate_dedup_users["wolverine"] = "shane"; | ||||||
|  | $migrate_dedup_users["schwarz"] = "wene"; | ||||||
|  | $migrate_dedup_users["justtesting"] = "levon"; | ||||||
|  | $migrate_dedup_users["erwin_xnan"] = "erwin"; | ||||||
|  | $migrate_dedup_users["zack"] = "krystof"; | ||||||
|  | $migrate_dedup_users["fabinator31"] = "fab31"; | ||||||
|  | $migrate_dedup_users["themilkman"] = "cliftonium"; | ||||||
|  | $migrate_dedup_users["etiennel"] = "choupi"; | ||||||
|  | $migrate_dedup_users["m_i_c_h_e_l"] = "michaels"; | ||||||
|  | $migrate_dedup_users["techrolla"] = "muffinpeddler"; | ||||||
|  | $migrate_dedup_users["fireflymantis"] = "twilight"; | ||||||
|  | $migrate_dedup_users["pinucset0"] = "pinucset"; | ||||||
|  | $migrate_dedup_users["franzrogar"] = "blender-i18n-po"; | ||||||
|  | $migrate_dedup_users["pinucset1"] = "pinucset"; | ||||||
|  | $migrate_dedup_users["pinucset3"] = "pinucset"; | ||||||
|  | $migrate_dedup_users["threeddream"] = "x-axis"; | ||||||
|  | $migrate_dedup_users["mudbot"] = "laurence"; | ||||||
|  | $migrate_dedup_users["ligeyx"] = "ligey"; | ||||||
|  | $migrate_dedup_users["dreas"] = "dre"; | ||||||
|  | $migrate_dedup_users["joorvapl"] = "joorva"; | ||||||
|  | $migrate_dedup_users["voyage"] = "xenithi"; | ||||||
|  | $migrate_dedup_users["azter"] = "azterix"; | ||||||
|  | $migrate_dedup_users["lapinbleu"] = "simeon"; | ||||||
|  | $migrate_dedup_users["emmanuel_t"] = "emmanuel"; | ||||||
|  | $migrate_dedup_users["cricket"] = "gku"; | ||||||
|  | $migrate_dedup_users["justanumber"] = "mad4linux"; | ||||||
|  | $migrate_dedup_users["johnnyen"] = "johnny"; | ||||||
|  | $migrate_dedup_users["leiota"] = "marcopolo"; | ||||||
|  | $migrate_dedup_users["blackstorm"] = "ikbendirk"; | ||||||
|  | $migrate_dedup_users["richie"] = "ligey"; | ||||||
|  | $migrate_dedup_users["mrcarnivore2"] = "mrcarnivore"; | ||||||
|  | $migrate_dedup_users["muddym1nd"] = "muddymind"; | ||||||
|  | $migrate_dedup_users["eumesmo"] = "vasco_da_gama"; | ||||||
|  | $migrate_dedup_users["ph-kby"] = "olav"; | ||||||
|  | $migrate_dedup_users["piotrek_"] = "ccpiotr"; | ||||||
|  | $migrate_dedup_users["joaquin"] = "prospero"; | ||||||
|  | $migrate_dedup_users["konrad_haenel"] = "konrad8ha"; | ||||||
|  | $migrate_dedup_users["benstabler"] = "lightning"; | ||||||
|  | $migrate_dedup_users["gustav"] = "draknoid"; | ||||||
|  | $migrate_dedup_users["slikdigit"] = "bassamk"; | ||||||
|  | $migrate_dedup_users["karlerlandsen"] = "lethalsidep"; | ||||||
|  | $migrate_dedup_users["djwillmsoh"] = "djw1"; | ||||||
|  | $migrate_dedup_users["aschmitz"] = "root_42"; | ||||||
|  | $migrate_dedup_users["malfunc"] = "mcq"; | ||||||
|  | $migrate_dedup_users["m_jack"] = "jack"; | ||||||
|  | $migrate_dedup_users["davey"] = "madcow"; | ||||||
|  | $migrate_dedup_users["iraytrace"] = "butler"; | ||||||
|  | $migrate_dedup_users["duser"] = "mslechols"; | ||||||
|  | $migrate_dedup_users["akito"] = "ton"; | ||||||
|  | $migrate_dedup_users["jochenschmitt"] = "s4504kr"; | ||||||
|  | $migrate_dedup_users["digikiller"] = "ace1"; | ||||||
|  | $migrate_dedup_users["shzhc"] = "zzzz"; | ||||||
|  | $migrate_dedup_users["cyrilbrulebois"] = "kibi"; | ||||||
|  | $migrate_dedup_users["themushroom"] = "draknoid"; | ||||||
|  | $migrate_dedup_users["zinkmaster"] = "mariolink"; | ||||||
|  | $migrate_dedup_users["ashsid"] = "ash"; | ||||||
|  | $migrate_dedup_users["novato"] = "jimenez"; | ||||||
|  | $migrate_dedup_users["jadie_p"] = "jadie"; | ||||||
|  | $migrate_dedup_users["neshshah007"] = "neshrai"; | ||||||
|  | $migrate_dedup_users["ryanshow"] = "tankcoder"; | ||||||
|  | $migrate_dedup_users["squarelinesq"] = "squareline"; | ||||||
|  | $migrate_dedup_users["virginijus"] = "ernestas1994"; | ||||||
|  | $migrate_dedup_users["renderdemon"] = "pnio"; | ||||||
|  | $migrate_dedup_users["kwab"] = "kobi"; | ||||||
|  | $migrate_dedup_users["peterjonckheere"] = "jonckheerep"; | ||||||
|  | $migrate_dedup_users["vidar"] = "vidarino"; | ||||||
|  | $migrate_dedup_users["sapjohannes"] = "johannesje"; | ||||||
|  | $migrate_dedup_users["youri"] = "ayers"; | ||||||
|  | $migrate_dedup_users["theamiman"] = "amiman"; | ||||||
|  | $migrate_dedup_users["chrisg_ksi"] = "red_planet"; | ||||||
|  | $migrate_dedup_users["blenderorgfan"] = "franciscosilva"; | ||||||
|  | $migrate_dedup_users["ericd"] = "ericdrayer"; | ||||||
|  | $migrate_dedup_users["asdfghjkl2"] = "asdfghjkl"; | ||||||
|  | $migrate_dedup_users["quorn"] = "alienit"; | ||||||
|  | $migrate_dedup_users["daan221"] = "phoenix221"; | ||||||
|  | $migrate_dedup_users["user"] = "mslechols"; | ||||||
|  | $migrate_dedup_users["pyb"] = "lomperillo"; | ||||||
|  | $migrate_dedup_users["g56"] = "gwald"; | ||||||
|  | $migrate_dedup_users["ausland"] = "vots"; | ||||||
|  | $migrate_dedup_users["quillinan"] = "orinoco"; | ||||||
|  | $migrate_dedup_users["t3tsuj1n"] = "bootsheoz"; | ||||||
|  | $migrate_dedup_users["molflesh"] = "melflash"; | ||||||
|  | $migrate_dedup_users["rickta59"] = "aerobicsboy"; | ||||||
|  | $migrate_dedup_users["nolopoly"] = "lopoly"; | ||||||
|  | $migrate_dedup_users["jeel"] = "jl57"; | ||||||
|  | $migrate_dedup_users["brianmccumber2"] = "brianmccumber"; | ||||||
|  | $migrate_dedup_users["mouette"] = "moutte"; | ||||||
|  | $migrate_dedup_users["wout"] = "wonderingwout"; | ||||||
|  | $migrate_dedup_users["fatfinger"] = "mattyc"; | ||||||
|  | $migrate_dedup_users["nathangull"] = "nateg"; | ||||||
|  | $migrate_dedup_users["tampadave"] = "dkmweeks"; | ||||||
|  | $migrate_dedup_users["sausages"] = "lethargic"; | ||||||
|  | $migrate_dedup_users["chris3d"] = "chrisbd"; | ||||||
|  | $migrate_dedup_users["kaito"] = "ton"; | ||||||
|  | $migrate_dedup_users["akirasan"] = "akira_b"; | ||||||
|  | $migrate_dedup_users["fiddle"] = "rayf"; | ||||||
|  | $migrate_dedup_users["bald"] = "manu"; | ||||||
|  | $migrate_dedup_users["mistermelquin"] = "melquin"; | ||||||
|  | $migrate_dedup_users["kofish"] = "kingdomoffish"; | ||||||
|  | $migrate_dedup_users["onanj"] = "orangee"; | ||||||
|  | $migrate_dedup_users["jasoncarrier"] = "jason"; | ||||||
|  | $migrate_dedup_users["joelgodin"] = "jenniferblender"; | ||||||
|  | $migrate_dedup_users["oranj"] = "orangee"; | ||||||
|  | $migrate_dedup_users["schdeb"] = "schmidtcristian"; | ||||||
|  | $migrate_dedup_users["bastian"] = "angerb"; | ||||||
|  | $migrate_dedup_users["patko"] = "patco"; | ||||||
|  | $migrate_dedup_users["arakyd666"] = "arakyd"; | ||||||
|  | $migrate_dedup_users["karimf"] = "rim-k"; | ||||||
|  | $migrate_dedup_users["nletwory"] = "jestertestest"; | ||||||
|  | $migrate_dedup_users["mansoorhyder"] = "mansoor"; | ||||||
|  | $migrate_dedup_users["rocketmagnet"] = "steventr"; | ||||||
|  | $migrate_dedup_users["thekernal"] = "kernal"; | ||||||
|  | $migrate_dedup_users["satom"] = "satriatomat"; | ||||||
|  | $migrate_dedup_users["a624"] = "a623"; | ||||||
|  | $migrate_dedup_users["jldavilacasares"] = "muki"; | ||||||
|  | $migrate_dedup_users["segersj"] = "segers"; | ||||||
|  | $migrate_dedup_users["hoisan49"] = "hoisan"; | ||||||
|  | $migrate_dedup_users["j_bessette"] = "linuxpimp20"; | ||||||
|  | $migrate_dedup_users["andreas999"] = "andreas"; | ||||||
|  | $migrate_dedup_users["dusan"] = "dsc512"; | ||||||
|  | $migrate_dedup_users["dx-mon"] = "mantr100"; | ||||||
|  | $migrate_dedup_users["ilislab"] = "ids"; | ||||||
|  | $migrate_dedup_users["rben"] = "raybenjamin"; | ||||||
|  | $migrate_dedup_users["sphere"] = "dysonsphere"; | ||||||
|  | $migrate_dedup_users["highlife22"] = "highlife"; | ||||||
|  | $migrate_dedup_users["yonarw"] = "yona"; | ||||||
|  | $migrate_dedup_users["kryptic89"] = "kryptic"; | ||||||
|  | $migrate_dedup_users["axelp"] = "axel"; | ||||||
|  | $migrate_dedup_users["perebalsach"] = "fog22"; | ||||||
|  | $migrate_dedup_users["alogerson"] = "gerson"; | ||||||
|  | $migrate_dedup_users["cotejrp"] = "cotejrp1"; | ||||||
|  | $migrate_dedup_users["tak"] = "carlosjamesr"; | ||||||
|  | $migrate_dedup_users["ziddy"] = "anishchandran"; | ||||||
|  | $migrate_dedup_users["asdgz"] = "blenderiseur"; | ||||||
|  | $migrate_dedup_users["cdated"] = "cdated257"; | ||||||
|  | $migrate_dedup_users["jayrkalugin"] = "jayr"; | ||||||
|  | $migrate_dedup_users["zeemzoet"] = "johannesje"; | ||||||
|  | $migrate_dedup_users["duo"] = "ambyra"; | ||||||
|  | $migrate_dedup_users["philb"] = "chewbacca"; | ||||||
|  | $migrate_dedup_users["tzi"] = "izt"; | ||||||
|  | $migrate_dedup_users["squirrelthetire"] = "squirrel-tire"; | ||||||
|  | $migrate_dedup_users["anwyn"] = "sugarshark"; | ||||||
|  | $migrate_dedup_users["a2z"] = "a2zaa"; | ||||||
|  | $migrate_dedup_users["fxrex"] = "femi"; | ||||||
|  | $migrate_dedup_users["alethewiz"] = "mfaso68"; | ||||||
|  | $migrate_dedup_users["noseferrit"] = "billybong"; | ||||||
|  | $migrate_dedup_users["fcali"] = "fabz"; | ||||||
|  | $migrate_dedup_users["bbirchler"] = "bblender"; | ||||||
|  | $migrate_dedup_users["oslosewers"] = "oslo"; | ||||||
|  | $migrate_dedup_users["wtrsltnk"] = "wtr"; | ||||||
|  | $migrate_dedup_users["cspohst"] = "spohst"; | ||||||
|  | $migrate_dedup_users["warhawk08"] = "warhawk1990"; | ||||||
|  | $migrate_dedup_users["magick_crow"] = "magickcrow"; | ||||||
|  | $migrate_dedup_users["guillaumem"] = "guillaume"; | ||||||
|  | $migrate_dedup_users["jwitthuhn"] = "rahu"; | ||||||
|  | $migrate_dedup_users["fmehigan"] = "frank_me"; | ||||||
|  | $migrate_dedup_users["ilissys"] = "ids"; | ||||||
|  | $migrate_dedup_users["supermoaaa"] = "moaaa"; | ||||||
|  | $migrate_dedup_users["nwmatt"] = "mhenley"; | ||||||
|  | $migrate_dedup_users["bezel"] = "xshell"; | ||||||
|  | $migrate_dedup_users["rebuss"] = "studioa"; | ||||||
|  | $migrate_dedup_users["geonom"] = "geoadel"; | ||||||
|  | $migrate_dedup_users["seldan"] = "farakon"; | ||||||
|  | $migrate_dedup_users["kuru76"] = "kcorbin"; | ||||||
|  | $migrate_dedup_users["kapil"] = "kapilbedarkar"; | ||||||
|  | $migrate_dedup_users["henryiii"] = "henryschreiner"; | ||||||
|  | $migrate_dedup_users["pateamcarl"] = "carlhuth"; | ||||||
|  | $migrate_dedup_users["kamen"] = "bigbob1993"; | ||||||
|  | $migrate_dedup_users["olddemon"] = "old_demon"; | ||||||
|  | $migrate_dedup_users["draklaw2"] = "draklaw"; | ||||||
|  | $migrate_dedup_users["ksdlee"] = "kdlee"; | ||||||
|  | $migrate_dedup_users["xource"] = "admix"; | ||||||
|  | $migrate_dedup_users["invertednormal"] = "smokebox46and2"; | ||||||
|  | $migrate_dedup_users["feelgoodcomics"] = "onlygoodwin"; | ||||||
|  | $migrate_dedup_users["glorund"] = "undolaure"; | ||||||
|  | $migrate_dedup_users["soulofsound"] = "johnnym"; | ||||||
|  | $migrate_dedup_users["ghigi123"] = "ghigi"; | ||||||
|  | $migrate_dedup_users["stefanvoigthpi"] = "derstefan"; | ||||||
|  | $migrate_dedup_users["dblenderv"] = "default"; | ||||||
|  | $migrate_dedup_users["ophiocus"] = "oneliner"; | ||||||
|  | $migrate_dedup_users["colleywrks"] = "colley"; | ||||||
|  | $migrate_dedup_users["fogy"] = "fog22"; | ||||||
|  | $migrate_dedup_users["vidarn"] = "bida70"; | ||||||
|  | $migrate_dedup_users["kevin"] = "goblender2541"; | ||||||
|  | $migrate_dedup_users["tisachris"] = "warflight"; | ||||||
|  | $migrate_dedup_users["personalex2"] = "personalex"; | ||||||
|  | $migrate_dedup_users["polypa"] = "lile"; | ||||||
|  | $migrate_dedup_users["i4dnf"] = "emilian"; | ||||||
|  | $migrate_dedup_users["nitalleb"] = "singleman"; | ||||||
|  | $migrate_dedup_users["tcgodoy"] = "godoy"; | ||||||
|  | $migrate_dedup_users["joorva_pl"] = "joorva"; | ||||||
|  | $migrate_dedup_users["sex"] = "xest"; | ||||||
|  | $migrate_dedup_users["chipmunk"] = "ignatz"; | ||||||
|  | $migrate_dedup_users["schalmagne"] = "chalmagne"; | ||||||
|  | $migrate_dedup_users["michalziulek"] = "eneida"; | ||||||
|  | $migrate_dedup_users["jeeps"] = "jeepster"; | ||||||
|  | $migrate_dedup_users["yain"] = "chaos"; | ||||||
|  | $migrate_dedup_users["amadio"] = "marble"; | ||||||
|  | $migrate_dedup_users["javiere"] = "javierchavez"; | ||||||
|  | $migrate_dedup_users["drmzperx"] = "mzperx"; | ||||||
|  | $migrate_dedup_users["sebastianreaser"] = "sebastian0"; | ||||||
|  | $migrate_dedup_users["idolon"] = "spadija"; | ||||||
|  | $migrate_dedup_users["alanhzhcn"] = "alanhzh"; | ||||||
|  | $migrate_dedup_users["jeanc"] = "jean"; | ||||||
|  | $migrate_dedup_users["transblue2"] = "transblue"; | ||||||
|  | $migrate_dedup_users["cesarwilfredo"] = "cesar"; | ||||||
|  | $migrate_dedup_users["nspyr"] = "spiderfire"; | ||||||
|  | $migrate_dedup_users["supermegamoaaa"] = "moaaa"; | ||||||
|  | $migrate_dedup_users["firetiger"] = "opensolution"; | ||||||
|  | $migrate_dedup_users["skarg"] = "cados"; | ||||||
|  | $migrate_dedup_users["realheadcrusher"] = "danigr"; | ||||||
|  | $migrate_dedup_users["kpg"] = "nihylius"; | ||||||
|  | $migrate_dedup_users["tft"] = "tft67"; | ||||||
|  | $migrate_dedup_users["storabbarn"] = "morre"; | ||||||
|  | $migrate_dedup_users["bacurau"] = "roger_roo"; | ||||||
|  | $migrate_dedup_users["alisari"] = "parasoley"; | ||||||
|  | $migrate_dedup_users["skiski"] = "superrom"; | ||||||
|  | $migrate_dedup_users["halfninja"] = "nickh"; | ||||||
|  | $migrate_dedup_users["drell_develop"] = "drellex"; | ||||||
|  | $migrate_dedup_users["highlif3"] = "highlife"; | ||||||
|  | $migrate_dedup_users["broggsim1"] = "broggsim"; | ||||||
|  | $migrate_dedup_users["blendermanuci"] = "yunior88"; | ||||||
|  | $migrate_dedup_users["jpt9"] = "jtuttle"; | ||||||
|  | $migrate_dedup_users["farrer"] = "farpro"; | ||||||
|  | $migrate_dedup_users["badcheez"] = "randall"; | ||||||
|  | $migrate_dedup_users["leewj_"] = "lohns"; | ||||||
|  | $migrate_dedup_users["martin107"] = "martinfrances"; | ||||||
|  | $migrate_dedup_users["dedpan"] = "tberghuis"; | ||||||
|  | $migrate_dedup_users["whiterabbit"] = "dreamscapearts"; | ||||||
|  | $migrate_dedup_users["shuvro"] = "shuvro05"; | ||||||
|  | $migrate_dedup_users["anichandru"] = "anishchandran"; | ||||||
|  | $migrate_dedup_users["ncaralph"] = "ralphdoctorow"; | ||||||
|  | $migrate_dedup_users["nlongchamps"] = "nlong"; | ||||||
|  | $migrate_dedup_users["mawi37"] = "mawi"; | ||||||
|  | $migrate_dedup_users["rizla"] = "jay"; | ||||||
|  | $migrate_dedup_users["jeh"] = "mirkril"; | ||||||
|  | $migrate_dedup_users["b-fighter"] = "fanatic"; | ||||||
|  | $migrate_dedup_users["wasamonkey"] = "wasa"; | ||||||
|  | $migrate_dedup_users["nicola"] = "martin45"; | ||||||
|  | $migrate_dedup_users["method-es"] = "method"; | ||||||
|  | $migrate_dedup_users["pablow"] = "warhole"; | ||||||
|  | $migrate_dedup_users["alanishzh"] = "alanhzh"; | ||||||
|  | $migrate_dedup_users["thunder947"] = "thunder"; | ||||||
|  | $migrate_dedup_users["yijimi"] = "roler"; | ||||||
|  | $migrate_dedup_users["jaydenb"] = "logidude"; | ||||||
|  | $migrate_dedup_users["leandropolus"] = "leandrosz"; | ||||||
|  | $migrate_dedup_users["ibi002"] = "ibi001"; | ||||||
|  | $migrate_dedup_users["hakanortasoz"] = "tayfax"; | ||||||
|  | $migrate_dedup_users["enur"] = "rune"; | ||||||
|  | $migrate_dedup_users["dsuesse"] = "qiip"; | ||||||
|  | $migrate_dedup_users["bipedlaboratory"] = "redmetal"; | ||||||
|  | $migrate_dedup_users["codeyhanson"] = "codey"; | ||||||
|  | $migrate_dedup_users["alphonso_b"] = "alfonso_b"; | ||||||
|  | $migrate_dedup_users["surreal6"] = "carlospadial"; | ||||||
|  | $migrate_dedup_users["kralizek"] = "kral"; | ||||||
|  | $migrate_dedup_users["kfrechet"] = "keithfr"; | ||||||
|  | $migrate_dedup_users["jwedlake"] = "joshwedlake"; | ||||||
|  | $migrate_dedup_users["westie630"] = "bully"; | ||||||
|  | $migrate_dedup_users["fictional"] = "icefire"; | ||||||
|  | $migrate_dedup_users["zelozelos"] = "zelozelos1"; | ||||||
|  | $migrate_dedup_users["dragonlord"] = "acuena"; | ||||||
|  | $migrate_dedup_users["mrcheese"] = "jpeg"; | ||||||
|  | $migrate_dedup_users["willemverwey"] = "dandandan"; | ||||||
|  | $migrate_dedup_users["jhed"] = "anton_foy"; | ||||||
|  | $migrate_dedup_users["treacy1077"] = "briant"; | ||||||
|  | $migrate_dedup_users["xest"] = "xembie"; | ||||||
|  | $migrate_dedup_users["cyphl25"] = "jmsfreezer"; | ||||||
|  | $migrate_dedup_users["wynk"] = "wynn"; | ||||||
|  | $migrate_dedup_users["trock2957"] = "trock"; | ||||||
|  | $migrate_dedup_users["mr_bomb"] = "carter24"; | ||||||
|  | $migrate_dedup_users["nikolaus"] = "tortellini"; | ||||||
|  | $migrate_dedup_users["pegasus_001"] = "pegasus001"; | ||||||
|  | $migrate_dedup_users["fayte"] = "fayte220"; | ||||||
|  | $migrate_dedup_users["jagang_8"] = "jagang"; | ||||||
|  | $migrate_dedup_users["thetwom"] = "moe"; | ||||||
|  | $migrate_dedup_users["kevlareditor"] = "klthomas"; | ||||||
|  | $migrate_dedup_users["damien_deom"] = "dams"; | ||||||
|  | $migrate_dedup_users["reynantem"] = "reynante"; | ||||||
|  | $migrate_dedup_users["hiralm01"] = "hiralm"; | ||||||
|  | $migrate_dedup_users["radix7"] = "wyldethang"; | ||||||
|  | $migrate_dedup_users["puppetm"] = "puppetmaster"; | ||||||
|  | $migrate_dedup_users["vimax"] = "vimaxus"; | ||||||
|  | $migrate_dedup_users["mozzy69"] = "lyndon"; | ||||||
|  | $migrate_dedup_users["vitranaccad"] = "thestorm74"; | ||||||
|  | $migrate_dedup_users["kj12345"] = "kevinjames"; | ||||||
|  | $migrate_dedup_users["foinix"] = "mrnoodle"; | ||||||
|  | $migrate_dedup_users["shizu"] = "sntulix"; | ||||||
|  | $migrate_dedup_users["kukulcangod23"] = "kukulcangod"; | ||||||
|  | $migrate_dedup_users["piliq"] = "qpblendpolis"; | ||||||
|  | $migrate_dedup_users["benvad"] = "vbenny"; | ||||||
|  | $migrate_dedup_users["fgribben"] = "sharkey"; | ||||||
|  | $migrate_dedup_users["makospince"] = "mako_spince"; | ||||||
|  | $migrate_dedup_users["ablenderuser"] = "pancakeface"; | ||||||
|  | $migrate_dedup_users["axelphi"] = "axel"; | ||||||
|  | $migrate_dedup_users["josiasbh"] = "josias"; | ||||||
|  | $migrate_dedup_users["mattsix"] = "majawe"; | ||||||
|  | $migrate_dedup_users["duarte_ramos"] = "dphantom"; | ||||||
|  | $migrate_dedup_users["killogge"] = "muraj"; | ||||||
|  | $migrate_dedup_users["luka"] = "omgwtfbbq"; | ||||||
|  | $migrate_dedup_users["chromemonkey"] = "brian651msp"; | ||||||
|  | $migrate_dedup_users["e_d_i"] = "ide"; | ||||||
|  | $migrate_dedup_users["mrhaynesy"] = "haynesy"; | ||||||
|  | $migrate_dedup_users["imagineering"] = "imagineer"; | ||||||
|  | $migrate_dedup_users["virgiliovasconc"] = "virgilio"; | ||||||
|  | $migrate_dedup_users["blenderlb57"] = "louigi"; | ||||||
|  | $migrate_dedup_users["nick65"] = "dgnicola"; | ||||||
|  | $migrate_dedup_users["mmatthews"] = "mamatthews"; | ||||||
|  | $migrate_dedup_users["gerwood"] = "arilian"; | ||||||
|  | $migrate_dedup_users["xsidmax"] = "xsi"; | ||||||
|  | $migrate_dedup_users["mix-yag"] = "aynahsim"; | ||||||
|  | $migrate_dedup_users["wpthomas"] = "tallguy"; | ||||||
|  | $migrate_dedup_users["bp007"] = "bender007"; | ||||||
|  | $migrate_dedup_users["emach"] = "eon4blender"; | ||||||
|  | $migrate_dedup_users["alfclement"] = "alfc"; | ||||||
|  | $migrate_dedup_users["blenderwell"] = "goplexian"; | ||||||
|  | $migrate_dedup_users["asebastianr"] = "sebastian0"; | ||||||
|  | $migrate_dedup_users["joepal1976"] = "joepal"; | ||||||
|  | $migrate_dedup_users["chertov"] = "lestat"; | ||||||
|  | $migrate_dedup_users["djela63"] = "jerominovich"; | ||||||
|  | $migrate_dedup_users["lppinto"] = "lpciper"; | ||||||
|  | $migrate_dedup_users["prana"] = "nomath"; | ||||||
|  | $migrate_dedup_users["sarubadoru"] = "salvador"; | ||||||
|  | $migrate_dedup_users["rarebit"] = "rawstar7"; | ||||||
|  | $migrate_dedup_users["hikikamori"] = "hikkikamori"; | ||||||
|  | $migrate_dedup_users["mrduke"] = "drop"; | ||||||
|  | $migrate_dedup_users["deetee"] = "dertee"; | ||||||
|  | $migrate_dedup_users["woooooah"] = "noxwell"; | ||||||
|  | $migrate_dedup_users["macoss"] = "ossmac"; | ||||||
|  | $migrate_dedup_users["bunnyboy212"] = "blender_buddie"; | ||||||
|  | $migrate_dedup_users["maxgrip"] = "czarek"; | ||||||
|  | $migrate_dedup_users["tentonman"] = "titandtat"; | ||||||
|  | $migrate_dedup_users["jabozzo"] = "bozzo"; | ||||||
|  | $migrate_dedup_users["reinways"] = "reinw"; | ||||||
|  | $migrate_dedup_users["petergk"] = "nihylius"; | ||||||
|  | $migrate_dedup_users["zphr3000"] = "zphr"; | ||||||
|  | $migrate_dedup_users["ruivo"] = "andreh"; | ||||||
|  | $migrate_dedup_users["kosta"] = "kgd"; | ||||||
|  | $migrate_dedup_users["delter"] = "dertee"; | ||||||
|  | $migrate_dedup_users["jmiller"] = "lethargic"; | ||||||
|  | $migrate_dedup_users["dealga"] = "zeffii"; | ||||||
|  | $migrate_dedup_users["bogey"] = "daveh"; | ||||||
|  | $migrate_dedup_users["silencebe"] = "silence"; | ||||||
|  | $migrate_dedup_users["temozarela"] = "gorn"; | ||||||
|  | $migrate_dedup_users["tischite"] = "greenbutton"; | ||||||
|  | $migrate_dedup_users["buisson"] = "dinodino"; | ||||||
|  | $migrate_dedup_users["cfox"] = "colinfox"; | ||||||
|  | $migrate_dedup_users["hunkadoodle"] = "hunkadoodledoo"; | ||||||
|  | $migrate_dedup_users["jlwitthuhn"] = "rahu"; | ||||||
|  | $migrate_dedup_users["hvfrancesco"] = "hva"; | ||||||
|  | $migrate_dedup_users["hazim-jamal"] = "hazim1"; | ||||||
|  | $migrate_dedup_users["aurosutru"] = "tlm"; | ||||||
|  | $migrate_dedup_users["pierrea"] = "pier2"; | ||||||
|  | $migrate_dedup_users["zoon"] = "zoonpolygonikon"; | ||||||
|  | $migrate_dedup_users["gruntbatch"] = "carmichael"; | ||||||
|  | $migrate_dedup_users["petru"] = "virusanti"; | ||||||
|  | $migrate_dedup_users["mikeh74"] = "mikeh"; | ||||||
|  | $migrate_dedup_users["sugoi"] = "juntunen"; | ||||||
|  | $migrate_dedup_users["bartje"] = "bartart3d"; | ||||||
|  | $migrate_dedup_users["yaoyansi"] = "yaoyansi2"; | ||||||
|  | $migrate_dedup_users["rafek"] = "rafek_finearts"; | ||||||
|  | $migrate_dedup_users["caspern"] = "caspernilsson"; | ||||||
|  | $migrate_dedup_users["lee"] = "s_random"; | ||||||
|  | $migrate_dedup_users["sparky"] = "mmikkelsen"; | ||||||
|  | $migrate_dedup_users["wigglyframes"] = "rene"; | ||||||
|  | $migrate_dedup_users["kroni"] = "kronos"; | ||||||
|  | $migrate_dedup_users["xgl_asyliax"] = "xglasyliax"; | ||||||
|  | $migrate_dedup_users["blendeador"] = "luisperosio"; | ||||||
|  | $migrate_dedup_users["kaos1986"] = "kaos86"; | ||||||
|  | $migrate_dedup_users["adamdoyle"] = "advs89"; | ||||||
|  | $migrate_dedup_users["kahenraz"] = "mistrel"; | ||||||
|  | $migrate_dedup_users["ccliffe"] = "cjcliffe"; | ||||||
|  | $migrate_dedup_users["nullfied"] = "xercesblue"; | ||||||
|  | $migrate_dedup_users["dustyghost"] = "dustbin1_uk"; | ||||||
|  | $migrate_dedup_users["claaskuhnen"] = "cekuhnendev"; | ||||||
|  | $migrate_dedup_users["vercingetorix"] = "diamond_rust"; | ||||||
|  | $migrate_dedup_users["plugboy"] = "centerlaw"; | ||||||
|  | $migrate_dedup_users["rben13"] = "raybenjamin"; | ||||||
|  | $migrate_dedup_users["deangiberson"] = "voidptr"; | ||||||
|  | $migrate_dedup_users["makeitwork"] = "bboybram"; | ||||||
|  | $migrate_dedup_users["iljosli"] = "jos"; | ||||||
|  | $migrate_dedup_users["slowan"] = "slovan"; | ||||||
|  | $migrate_dedup_users["mooonwalkercz"] = "mooonwalker"; | ||||||
|  | $migrate_dedup_users["tapplek"] = "tapple"; | ||||||
|  | $migrate_dedup_users["blendmond"] = "cornix"; | ||||||
|  | $migrate_dedup_users["giorgiomartini"] = "tweakingknobs"; | ||||||
|  | $migrate_dedup_users["davidray"] = "deadman"; | ||||||
|  | $migrate_dedup_users["justthisguy"] = "nyctef"; | ||||||
|  | $migrate_dedup_users["logobar"] = "freyer"; | ||||||
|  | $migrate_dedup_users["zooo"] = "leon_cheung"; | ||||||
|  | $migrate_dedup_users["josiasalexandre"] = "josias"; | ||||||
|  | $migrate_dedup_users["tsukiko_chan"] = "tsukikochan"; | ||||||
|  | $migrate_dedup_users["akira_san"] = "akira_b"; | ||||||
|  | $migrate_dedup_users["walberti"] = "walbertievarist"; | ||||||
|  | $migrate_dedup_users["astro"] = "tnboma"; | ||||||
|  | $migrate_dedup_users["mccx"] = "mcq"; | ||||||
|  | $migrate_dedup_users["daa84"] = "daa"; | ||||||
|  | $migrate_dedup_users["sivert3"] = "cent"; | ||||||
|  | $migrate_dedup_users["twentyone"] = "glade"; | ||||||
|  | $migrate_dedup_users["endi2"] = "endi"; | ||||||
|  | $migrate_dedup_users["jamesr"] = "james_r"; | ||||||
|  | $migrate_dedup_users["reece"] = "reecerobinson"; | ||||||
|  | $migrate_dedup_users["dustractor"] = "bpygrams"; | ||||||
|  | $migrate_dedup_users["pencilhead"] = "pencil-head"; | ||||||
|  | $migrate_dedup_users["toml"] = "tomol"; | ||||||
|  | $migrate_dedup_users["colinm"] = "tablaman"; | ||||||
|  | $migrate_dedup_users["blendphys2"] = "blendphys"; | ||||||
|  | $migrate_dedup_users["xgoff"] = "zzyxz"; | ||||||
|  | $migrate_dedup_users["coleingraham"] = "coledingraham"; | ||||||
|  | $migrate_dedup_users["danielvmacedo"] = "skul3r"; | ||||||
|  | $migrate_dedup_users["burster"] = "przemaz"; | ||||||
|  | $migrate_dedup_users["tung"] = "tungster"; | ||||||
|  | $migrate_dedup_users["chessie"] = "blackcatt"; | ||||||
|  | $migrate_dedup_users["foxdog"] = "rubbernuke"; | ||||||
|  | $migrate_dedup_users["mordachai"] = "gus"; | ||||||
|  | $migrate_dedup_users["chilamlai"] = "cllai"; | ||||||
|  | $migrate_dedup_users["sliders34"] = "sliders"; | ||||||
|  | $migrate_dedup_users["benji852"] = "benjamin852"; | ||||||
|  | $migrate_dedup_users["bebinalpha"] = "bebin"; | ||||||
|  | $migrate_dedup_users["mr78"] = "alexandr"; | ||||||
|  | $migrate_dedup_users["avirillion"] = "tarion"; | ||||||
|  | $migrate_dedup_users["matthiasro"] = "matthias_r"; | ||||||
|  | $migrate_dedup_users["debearseax"] = "seogeniuss"; | ||||||
|  | $migrate_dedup_users["karja"] = "trockenfrosch"; | ||||||
|  | $migrate_dedup_users["rojuinex"] = "ifrit"; | ||||||
|  | $migrate_dedup_users["bernardo"] = "dados"; | ||||||
|  | $migrate_dedup_users["ddeclara"] = "decden"; | ||||||
|  | $migrate_dedup_users["zm_sansan"] = "sansan"; | ||||||
|  | $migrate_dedup_users["useless"] = "cortot"; | ||||||
|  | $migrate_dedup_users["tymnclono"] = "sooccatly"; | ||||||
|  | $migrate_dedup_users["rodrigo_b"] = "rodrigob"; | ||||||
|  | $migrate_dedup_users["shnurui"] = "spinster"; | ||||||
|  | $migrate_dedup_users["michalisz"] = "michaliszissiou"; | ||||||
|  | $migrate_dedup_users["fbbdev"] = "babboide"; | ||||||
|  | $migrate_dedup_users["tjackson"] = "tjonline"; | ||||||
|  | $migrate_dedup_users["ramaswamy"] = "ramaswamysriram"; | ||||||
|  | $migrate_dedup_users["allrod5"] = "rodblender"; | ||||||
|  | $migrate_dedup_users["qcp"] = "qpblendpolis"; | ||||||
|  | $migrate_dedup_users["ftsf"] = "thesleepless"; | ||||||
|  | $migrate_dedup_users["umagoo2012"] = "umagoo"; | ||||||
|  | $migrate_dedup_users["raven"] = "rune"; | ||||||
|  | $migrate_dedup_users["hsaito"] = "integer"; | ||||||
|  | $migrate_dedup_users["paulthegreat"] = "digitalpyro"; | ||||||
|  | $migrate_dedup_users["capheen"] = "dval"; | ||||||
|  | $migrate_dedup_users["rskinner"] = "rws"; | ||||||
|  | $migrate_dedup_users["gregstein"] = "gregorein"; | ||||||
|  | $migrate_dedup_users["matty686"] = "matty"; | ||||||
|  | $migrate_dedup_users["selby_rowley"] = "selby"; | ||||||
|  | $migrate_dedup_users["shembolstudio"] = "natadams8"; | ||||||
|  | $migrate_dedup_users["grenzfrequence"] = "goatrance"; | ||||||
|  | $migrate_dedup_users["stephan"] = "schdeffan"; | ||||||
|  | $migrate_dedup_users["axis33"] = "dsc512"; | ||||||
|  | $migrate_dedup_users["redandfish"] = "red-fish"; | ||||||
|  | $migrate_dedup_users["artsapcemedia"] = "arzpace"; | ||||||
|  | $migrate_dedup_users["artspacemedia"] = "arzpace"; | ||||||
|  | $migrate_dedup_users["mccmcc"] = "mcq"; | ||||||
|  | $migrate_dedup_users["seocitterx"] = "mediabuy"; | ||||||
|  | $migrate_dedup_users["lightning_limn"] = "lightning4"; | ||||||
|  | $migrate_dedup_users["omarlakhdar"] = "archimage"; | ||||||
|  | $migrate_dedup_users["regeleionescu"] = "regele"; | ||||||
|  | $migrate_dedup_users["mitchell_decker"] = "michealikruhara"; | ||||||
|  | $migrate_dedup_users["joselebon"] = "jl57"; | ||||||
|  | $migrate_dedup_users["simonbroggi"] = "broggsim"; | ||||||
|  | $migrate_dedup_users["inwadnepe"] = "ceapbatatry"; | ||||||
|  | $migrate_dedup_users["ehobjman"] = "resbsp"; | ||||||
|  | $migrate_dedup_users["davelassanske"] = "dolby411"; | ||||||
|  | $migrate_dedup_users["jsu"] = "jansub"; | ||||||
|  | $migrate_dedup_users["agricola"] = "agricola1"; | ||||||
|  | $migrate_dedup_users["bartoszek"] = "bartus"; | ||||||
|  | $migrate_dedup_users["captainoblivion"] = "cptoblivion"; | ||||||
|  | $migrate_dedup_users["alexmcourt"] = "personalex"; | ||||||
|  | $migrate_dedup_users["jmsprss"] = "xonar"; | ||||||
|  | $migrate_dedup_users["awarnock"] = "salsa"; | ||||||
|  | $migrate_dedup_users["mcc2"] = "mcq"; | ||||||
|  | $migrate_dedup_users["psyborg042"] = "psyborg"; | ||||||
|  | $migrate_dedup_users["ushiproject"] = "ushi"; | ||||||
|  | $migrate_dedup_users["mrjimmy"] = "mrjimmyos"; | ||||||
|  | $migrate_dedup_users["thefinalcut"] = "tlousky"; | ||||||
|  | $migrate_dedup_users["startheshadow"] = "star"; | ||||||
|  | $migrate_dedup_users["axredneck"] = "redneck"; | ||||||
|  | $migrate_dedup_users["phimestudio"] = "phime"; | ||||||
|  | $migrate_dedup_users["dwatts1"] = "dlax"; | ||||||
|  | $migrate_dedup_users["rertjoi"] = "rertjwi"; | ||||||
|  | $migrate_dedup_users["erdjkgh"] = "rertjwi"; | ||||||
|  | $migrate_dedup_users["libertainsrg"] = "fcougar"; | ||||||
|  | $migrate_dedup_users["godling72"] = "dmelchio"; | ||||||
|  | $migrate_dedup_users["myclay"] = "thenewone"; | ||||||
|  | $migrate_dedup_users["ecaspersen"] = "ecasper"; | ||||||
|  | $migrate_dedup_users["driewiel"] = "driesiedriewiel"; | ||||||
|  | $migrate_dedup_users["bhupen"] = "bhupendra"; | ||||||
|  | $migrate_dedup_users["caosdoar"] = "mailoyo"; | ||||||
|  | $migrate_dedup_users["polyspin"] = "butler"; | ||||||
|  | $migrate_dedup_users["qalb_al_aqrab"] = "efimpetelin"; | ||||||
|  | $migrate_dedup_users["fdfdfdfffd"] = "fcougar"; | ||||||
|  | $migrate_dedup_users["brianlockett"] = "macrow"; | ||||||
|  | $migrate_dedup_users["claude"] = "coco"; | ||||||
|  | $migrate_dedup_users["mattostgard"] = "drflail"; | ||||||
|  | $migrate_dedup_users["cekuhnen_new"] = "cekuhnendev"; | ||||||
|  | $migrate_dedup_users["kirill_lukyanov"] = "kirill"; | ||||||
|  | $migrate_dedup_users["jan-eric"] = "janeric96"; | ||||||
|  | $migrate_dedup_users["daniel_h"] = "dhoughto"; | ||||||
|  | $migrate_dedup_users["raphaelbarros"] = "thebigheadone"; | ||||||
|  | $migrate_dedup_users["salas"] = "tychota"; | ||||||
|  | $migrate_dedup_users["danieljsamson"] = "techfix"; | ||||||
|  | $migrate_dedup_users["vinagrito"] = "aechemendia"; | ||||||
|  | $migrate_dedup_users["lin_165"] = "b1657022405"; | ||||||
|  | $migrate_dedup_users["cwebber"] = "paroneayea"; | ||||||
|  | $migrate_dedup_users["harolddadomo"] = "harold"; | ||||||
|  | $migrate_dedup_users["rabidsquirrel"] = "genericusername"; | ||||||
|  | $migrate_dedup_users["larry3"] = "lehibou"; | ||||||
|  | $migrate_dedup_users["predoe"] = "petronius3d"; | ||||||
|  | $migrate_dedup_users["skoo"] = "stefano"; | ||||||
|  | $migrate_dedup_users["cabergolinety"] = "azathioprinewww"; | ||||||
|  | $migrate_dedup_users["prestijkorsan07"] = "prestij07"; | ||||||
|  | $migrate_dedup_users["scottpetrovic"] = "slpetrov"; | ||||||
|  | $migrate_dedup_users["zooly76"] = "zooly"; | ||||||
|  | $migrate_dedup_users["theoryanimation"] = "davidandrade"; | ||||||
|  | $migrate_dedup_users["daninsky"] = "danishit"; | ||||||
|  | $migrate_dedup_users["eyesee2013"] = "eyesee"; | ||||||
|  | $migrate_dedup_users["megacal"] = "cmcgaugh"; | ||||||
|  | $migrate_dedup_users["const"] = "kostas100"; | ||||||
|  | $migrate_dedup_users["ngaudenzi"] = "puppetmaster"; | ||||||
|  | $migrate_dedup_users["mroguski"] = "kaelthas"; | ||||||
|  | $migrate_dedup_users["brdf"] = "origin"; | ||||||
|  | $migrate_dedup_users["davis3d"] = "davis"; | ||||||
|  | $migrate_dedup_users["rldigital"] = "locatelli"; | ||||||
|  | $migrate_dedup_users["tomforsythe"] = "gallifrey77203"; | ||||||
|  | $migrate_dedup_users["gbrnk"] = "benoe"; | ||||||
|  | $migrate_dedup_users["arekkasprzyk"] = "kasperski"; | ||||||
|  | $migrate_dedup_users["imbusy1"] = "imbusy"; | ||||||
|  | $migrate_dedup_users["mfoxdoggg"] = "mfoxdogg"; | ||||||
|  |  | ||||||
|  | $migrate_dedup_users["knusk"] = "kanutus"; | ||||||
|  | $migrate_dedup_users["tomekk"] = "anders211"; | ||||||
|  | $migrate_dedup_users["kitsueb"] = "kitsu_eb"; | ||||||
|  | $migrate_dedup_users["slugzzz"] = "tsquar3d"; | ||||||
|  | $migrate_dedup_users["moore500"] = "mmoore500"; | ||||||
|  | $migrate_dedup_users["verumbra"] = "sebastian0"; | ||||||
|  | $migrate_dedup_users["blenderbug"] = "nikola"; | ||||||
|  |  | ||||||
|  | $migrate_dedup_users["adailtoncomp"] = "adailton"; | ||||||
|  | $migrate_dedup_users["mchs3d"] = "abtrumpet"; | ||||||
|  |  | ||||||
|  | // disabled users who have tasks | ||||||
|  | $migrate_dedup_users["sjoerd"] = "sjoerddevries"; | ||||||
|  | $migrate_dedup_users["matali"] = "mat_ali"; | ||||||
|  | $migrate_dedup_users["voicelesscushio"] = "None"; | ||||||
|  | $migrate_dedup_users["bigben0328"] = "None"; | ||||||
|  | $migrate_dedup_users["santamouse"] = "None"; | ||||||
|  | $migrate_dedup_users["andreanckaert"] = "None"; | ||||||
|  | $migrate_dedup_users["yesmydear"] = "None"; | ||||||
|  | $migrate_dedup_users["spacetug"] = "None"; | ||||||
|  | $migrate_dedup_users["omegafold"] = "None"; | ||||||
|  |  | ||||||
|  | // testing | ||||||
|  | $migrate_dedup_users["blendix_rename_test_a"] = "blendix"; | ||||||
|  | $migrate_dedup_users["blendix_rename_test_b"] = "blendix"; | ||||||
|  |  | ||||||
| Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.8 KiB | 
| Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 11 KiB | 
| Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.4 KiB | 
| @@ -54,8 +54,6 @@ return array( | |||||||
|     'javelin-behavior-aphlict-dropdown', |     'javelin-behavior-aphlict-dropdown', | ||||||
|     'javelin-behavior-history-install', |     'javelin-behavior-history-install', | ||||||
|     'javelin-behavior-phabricator-gesture', |     'javelin-behavior-phabricator-gesture', | ||||||
|     'javelin-behavior-phabricator-active-nav', |  | ||||||
|     'javelin-behavior-phabricator-nav', |  | ||||||
|     'javelin-behavior-phabricator-remarkup-assist', |     'javelin-behavior-phabricator-remarkup-assist', | ||||||
|     'phabricator-textareautils', |     'phabricator-textareautils', | ||||||
|     'phabricator-file-upload', |     'phabricator-file-upload', | ||||||
| @@ -88,6 +86,12 @@ return array( | |||||||
|     'javelin-behavior-aphlict-status', |     'javelin-behavior-aphlict-status', | ||||||
|     'javelin-behavior-user-menu', |     'javelin-behavior-user-menu', | ||||||
|     'phabricator-favicon', |     'phabricator-favicon', | ||||||
|  |     'javelin-behavior-phui-tab-group', | ||||||
|  |     'javelin-behavior-phui-submenu', | ||||||
|  |     'phuix-button-view', | ||||||
|  |     'javelin-behavior-comment-actions', | ||||||
|  |     'phuix-form-control-view', | ||||||
|  |     'phuix-autocomplete', | ||||||
|   ), |   ), | ||||||
|   'core.pkg.css' => array( |   'core.pkg.css' => array( | ||||||
|     'phabricator-core-css', |     'phabricator-core-css', | ||||||
| @@ -158,9 +162,14 @@ return array( | |||||||
|     'phabricator-feed-css', |     'phabricator-feed-css', | ||||||
|     'phabricator-dashboard-css', |     'phabricator-dashboard-css', | ||||||
|     'aphront-multi-column-view-css', |     'aphront-multi-column-view-css', | ||||||
|  |     'phui-curtain-object-ref-view-css', | ||||||
|  |     'phui-comment-form-css', | ||||||
|  |     'phui-head-thing-view-css', | ||||||
|  |  | ||||||
|  |     'conpherence-durable-column-view', | ||||||
|  |     'phui-button-bar-css', | ||||||
|   ), |   ), | ||||||
|   'conpherence.pkg.css' => array( |   'conpherence.pkg.css' => array( | ||||||
|     'conpherence-durable-column-view', |  | ||||||
|     'conpherence-menu-css', |     'conpherence-menu-css', | ||||||
|     'conpherence-color-css', |     'conpherence-color-css', | ||||||
|     'conpherence-message-pane-css', |     'conpherence-message-pane-css', | ||||||
| @@ -187,7 +196,8 @@ return array( | |||||||
|     'phabricator-content-source-view-css', |     'phabricator-content-source-view-css', | ||||||
|     'inline-comment-summary-css', |     'inline-comment-summary-css', | ||||||
|     'phui-inline-comment-view-css', |     'phui-inline-comment-view-css', | ||||||
|     'phabricator-filetree-view-css', |     'diff-tree-view-css', | ||||||
|  |     'phui-formation-view-css', | ||||||
|   ), |   ), | ||||||
|   'differential.pkg.js' => array( |   'differential.pkg.js' => array( | ||||||
|     'phabricator-drag-and-drop-file-upload', |     'phabricator-drag-and-drop-file-upload', | ||||||
| @@ -204,6 +214,14 @@ return array( | |||||||
|     'phabricator-diff-inline', |     'phabricator-diff-inline', | ||||||
|     'phabricator-diff-changeset', |     'phabricator-diff-changeset', | ||||||
|     'phabricator-diff-changeset-list', |     'phabricator-diff-changeset-list', | ||||||
|  |     'phabricator-diff-tree-view', | ||||||
|  |     'phabricator-diff-path-view', | ||||||
|  |  | ||||||
|  |     'phuix-formation-view', | ||||||
|  |     'phuix-formation-column-view', | ||||||
|  |     'phuix-formation-flank-view', | ||||||
|  |  | ||||||
|  |     'javelin-external-editor-link-engine', | ||||||
|   ), |   ), | ||||||
|   'diffusion.pkg.css' => array( |   'diffusion.pkg.css' => array( | ||||||
|     'diffusion-icons-css', |     'diffusion-icons-css', | ||||||
| @@ -220,4 +238,9 @@ return array( | |||||||
|     'javelin-behavior-maniphest-batch-selector', |     'javelin-behavior-maniphest-batch-selector', | ||||||
|     'javelin-behavior-maniphest-list-editor', |     'javelin-behavior-maniphest-list-editor', | ||||||
|   ), |   ), | ||||||
|  |   'dark-console.pkg.js' => array( | ||||||
|  |     'javelin-behavior-dark-console', | ||||||
|  |     'phabricator-darklog', | ||||||
|  |     'phabricator-darkmessage', | ||||||
|  |   ), | ||||||
| ); | ); | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ $status_map = array( | |||||||
|   3 => 'invalid', |   3 => 'invalid', | ||||||
|   4 => 'duplicate', |   4 => 'duplicate', | ||||||
|   5 => 'spite', |   5 => 'spite', | ||||||
|  |   123450 => 'archived', | ||||||
| ); | ); | ||||||
|  |  | ||||||
| $conn_w = id(new ManiphestTask())->establishConnection('w'); | $conn_w = id(new ManiphestTask())->establishConnection('w'); | ||||||
|   | |||||||
| @@ -16,6 +16,9 @@ foreach (new LiskMigrationIterator($table) as $doc) { | |||||||
|     continue; |     continue; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   $new_view_policy = $default_view_policy; | ||||||
|  |   $new_edit_policy = $default_edit_policy; | ||||||
|  |  | ||||||
|   // If this was previously a magical project wiki page (under projects/, but |   // If this was previously a magical project wiki page (under projects/, but | ||||||
|   // not projects/ itself) we need to apply the project policies. Otherwise, |   // not projects/ itself) we need to apply the project policies. Otherwise, | ||||||
|   // apply the default policies. |   // apply the default policies. | ||||||
| @@ -35,26 +38,24 @@ foreach (new LiskMigrationIterator($table) as $doc) { | |||||||
|       ->executeOne(); |       ->executeOne(); | ||||||
|  |  | ||||||
|     if ($project) { |     if ($project) { | ||||||
|  |  | ||||||
|       $view_policy = nonempty($project->getViewPolicy(), $default_view_policy); |       $view_policy = nonempty($project->getViewPolicy(), $default_view_policy); | ||||||
|       $edit_policy = nonempty($project->getEditPolicy(), $default_edit_policy); |       $edit_policy = nonempty($project->getEditPolicy(), $default_edit_policy); | ||||||
|  |  | ||||||
|       $project_name = $project->getName(); |       $new_view_policy = $view_policy; | ||||||
|       echo pht( |       $new_edit_policy = $edit_policy; | ||||||
|         "Migrating document %d to project policy %s...\n", |  | ||||||
|         $id, |  | ||||||
|         $project_name); |  | ||||||
|       $doc->setViewPolicy($view_policy); |  | ||||||
|       $doc->setEditPolicy($edit_policy); |  | ||||||
|       $doc->save(); |  | ||||||
|       continue; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   echo pht('Migrating document %d to default install policy...', $id)."\n"; |   echo pht('Migrating document %d to new policy...', $id)."\n"; | ||||||
|   $doc->setViewPolicy($default_view_policy); |  | ||||||
|   $doc->setEditPolicy($default_edit_policy); |   queryfx( | ||||||
|   $doc->save(); |     $conn_w, | ||||||
|  |     'UPDATE %R SET viewPolicy = %s, editPolicy = %s | ||||||
|  |       WHERE id = %d', | ||||||
|  |     $table, | ||||||
|  |     $new_view_policy, | ||||||
|  |     $new_edit_policy, | ||||||
|  |     $id); | ||||||
| } | } | ||||||
|  |  | ||||||
| echo pht('Done.')."\n"; | echo pht('Done.')."\n"; | ||||||
|   | |||||||
| @@ -4,18 +4,8 @@ | |||||||
| // underlying file data were not written correctly. This restores edges for | // underlying file data were not written correctly. This restores edges for | ||||||
| // any missing pastes. | // any missing pastes. | ||||||
|  |  | ||||||
| $table = new PhabricatorPaste(); | // See T13510. The "pastebin" database was later renamed to "paste", which | ||||||
| $edge_type = PhabricatorObjectHasFileEdgeType::EDGECONST; | // broke this migration. The migration was removed in 2020 since it seems | ||||||
|  | // plausible that zero installs are impacted (only installs that ran code | ||||||
| foreach (new LiskMigrationIterator($table) as $paste) { | // from November 2015 and have not upgraded in five years could possibly be | ||||||
|   $paste_phid = $paste->getPHID(); | // impacted). | ||||||
|   $file_phid = $paste->getFilePHID(); |  | ||||||
|  |  | ||||||
|   if (!$file_phid) { |  | ||||||
|     continue; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   id(new PhabricatorEdgeEditor()) |  | ||||||
|     ->addEdge($paste_phid, $edge_type, $file_phid) |  | ||||||
|     ->save(); |  | ||||||
| } |  | ||||||
|   | |||||||
							
								
								
									
										10
									
								
								resources/sql/autopatches/20200220.xaccount.01.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,10 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_user.user_externalaccountidentifier ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   phid VARBINARY(64) NOT NULL, | ||||||
|  |   externalAccountPHID VARBINARY(64) NOT NULL, | ||||||
|  |   providerConfigPHID VARBINARY(64) NOT NULL, | ||||||
|  |   identifierHash BINARY(12) NOT NULL, | ||||||
|  |   identifierRaw LONGTEXT NOT NULL, | ||||||
|  |   dateCreated INT UNSIGNED NOT NULL, | ||||||
|  |   dateModified INT UNSIGNED NOT NULL | ||||||
|  | ) ENGINE=InnoDB DEFAULT CHARSET={$CHARSET} COLLATE {$COLLATE_TEXT}; | ||||||
							
								
								
									
										40
									
								
								resources/sql/autopatches/20200222.xident.01.migrate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,40 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $account_table = new PhabricatorExternalAccount(); | ||||||
|  | $identifier_table = new PhabricatorExternalAccountIdentifier(); | ||||||
|  |  | ||||||
|  | $conn = $account_table->establishConnection('w'); | ||||||
|  | $table_name = $account_table->getTableName(); | ||||||
|  |  | ||||||
|  | $iterator = new LiskRawMigrationIterator($conn, $table_name); | ||||||
|  | foreach ($iterator as $account_row) { | ||||||
|  |   // We don't need to migrate "accountID" values for "password" accounts, | ||||||
|  |   // since these were dummy values in the first place and are no longer | ||||||
|  |   // read or written after D21014. (There would be no harm in writing these | ||||||
|  |   // rows, but it's easy to skip them.) | ||||||
|  |  | ||||||
|  |   if ($account_row['accountType'] === 'password') { | ||||||
|  |     continue; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $account_id = $account_row['accountID']; | ||||||
|  |   if (!strlen($account_id)) { | ||||||
|  |     continue; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   queryfx( | ||||||
|  |     $conn, | ||||||
|  |     'INSERT IGNORE INTO %R ( | ||||||
|  |         phid, externalAccountPHID, providerConfigPHID, | ||||||
|  |         identifierHash, identifierRaw, | ||||||
|  |         dateCreated, dateModified) | ||||||
|  |       VALUES (%s, %s, %s, %s, %s, %d, %d)', | ||||||
|  |     $identifier_table, | ||||||
|  |     $identifier_table->generatePHID(), | ||||||
|  |     $account_row['phid'], | ||||||
|  |     $account_row['providerConfigPHID'], | ||||||
|  |     PhabricatorHash::digestForIndex($account_id), | ||||||
|  |     $account_id, | ||||||
|  |     $account_row['dateCreated'], | ||||||
|  |     $account_row['dateModified']); | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								resources/sql/autopatches/20200222.xident.02.dropkey.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,21 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | // See T13493. This table previously had a UNIQUE KEY on "<accountType, | ||||||
|  | // accountDomain, accountID>", which is obsolete. The application now violates | ||||||
|  | // this key, so make sure it gets dropped. | ||||||
|  |  | ||||||
|  | // There's no "IF EXISTS" modifier for "ALTER TABLE" so run this as a PHP patch | ||||||
|  | // instead of an SQL patch. | ||||||
|  |  | ||||||
|  | $table = new PhabricatorExternalAccount(); | ||||||
|  | $conn = $table->establishConnection('w'); | ||||||
|  |  | ||||||
|  | try { | ||||||
|  |   queryfx( | ||||||
|  |     $conn, | ||||||
|  |     'ALTER TABLE %R DROP KEY %T', | ||||||
|  |     $table, | ||||||
|  |     'account_details'); | ||||||
|  | } catch (AphrontQueryException $ex) { | ||||||
|  |   // Ignore. | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_paste.paste_paste_fdocument ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   objectPHID VARBINARY(64) NOT NULL, | ||||||
|  |   isClosed BOOL NOT NULL, | ||||||
|  |   authorPHID VARBINARY(64), | ||||||
|  |   ownerPHID VARBINARY(64), | ||||||
|  |   epochCreated INT UNSIGNED NOT NULL, | ||||||
|  |   epochModified INT UNSIGNED NOT NULL | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_paste.paste_paste_ffield ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   documentID INT UNSIGNED NOT NULL, | ||||||
|  |   fieldKey VARCHAR(4) NOT NULL COLLATE {$COLLATE_TEXT}, | ||||||
|  |   rawCorpus LONGTEXT NOT NULL COLLATE {$COLLATE_SORT}, | ||||||
|  |   termCorpus LONGTEXT NOT NULL COLLATE {$COLLATE_SORT}, | ||||||
|  |   normalCorpus LONGTEXT NOT NULL COLLATE {$COLLATE_SORT} | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,5 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_paste.paste_paste_fngrams ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   documentID INT UNSIGNED NOT NULL, | ||||||
|  |   ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT} | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_paste.paste_paste_fngrams_common ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   ngram CHAR(3) NOT NULL COLLATE {$COLLATE_TEXT}, | ||||||
|  |   needsCollection BOOL NOT NULL, | ||||||
|  |   UNIQUE KEY `key_ngram` (ngram), | ||||||
|  |   KEY `key_collect` (needsCollection) | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_differential.differential_viewstate ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   viewerPHID VARBINARY(64) NOT NULL, | ||||||
|  |   objectPHID VARBINARY(64) NOT NULL, | ||||||
|  |   viewState LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}, | ||||||
|  |   dateCreated INT UNSIGNED NOT NULL, | ||||||
|  |   dateModified INT UNSIGNED NOT NULL, | ||||||
|  |   UNIQUE KEY `key_viewer` (viewerPHID, objectPHID) | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,2 @@ | |||||||
|  | ALTER TABLE {$NAMESPACE}_differential.differential_transaction_comment | ||||||
|  |   ADD attributes LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,2 @@ | |||||||
|  | ALTER TABLE {$NAMESPACE}_audit.audit_transaction_comment | ||||||
|  |   ADD attributes LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1,2 @@ | |||||||
|  | UPDATE {$NAMESPACE}_differential.differential_transaction_comment | ||||||
|  |   SET attributes = '{}' WHERE attributes = ''; | ||||||
| @@ -0,0 +1,2 @@ | |||||||
|  | UPDATE {$NAMESPACE}_audit.audit_transaction_comment | ||||||
|  |   SET attributes = '{}' WHERE attributes = ''; | ||||||
| @@ -0,0 +1 @@ | |||||||
|  | DROP TABLE {$NAMESPACE}_differential.differential_changeset_parse_cache; | ||||||
| @@ -0,0 +1,7 @@ | |||||||
|  | CREATE TABLE {$NAMESPACE}_differential.differential_changeset_parse_cache ( | ||||||
|  |   id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, | ||||||
|  |   cacheIndex BINARY(12) NOT NULL, | ||||||
|  |   cache LONGBLOB NOT NULL, | ||||||
|  |   dateCreated INT UNSIGNED NOT NULL, | ||||||
|  |   UNIQUE KEY `key_cacheIndex` (cacheIndex) | ||||||
|  | ) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT}; | ||||||
| @@ -0,0 +1 @@ | |||||||
|  | DROP TABLE IF EXISTS {$NAMESPACE}_differential.differential_commit; | ||||||
							
								
								
									
										46
									
								
								resources/timezones/generate-timezone-map.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,46 @@ | |||||||
|  | #!/usr/bin/env php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $root = dirname(dirname(dirname(__FILE__))); | ||||||
|  | require_once $root.'/scripts/init/init-script.php'; | ||||||
|  |  | ||||||
|  | $xml = $root.'/externals/cldr/cldr_windows_timezones.xml'; | ||||||
|  | $xml = Filesystem::readFile($xml); | ||||||
|  | $xml = new SimpleXMLElement($xml); | ||||||
|  |  | ||||||
|  | $result_map = array(); | ||||||
|  |  | ||||||
|  | $ignore = array( | ||||||
|  |   'UTC', | ||||||
|  |   'UTC-11', | ||||||
|  |   'UTC-02', | ||||||
|  |   'UTC-08', | ||||||
|  |   'UTC-09', | ||||||
|  |   'UTC+12', | ||||||
|  | ); | ||||||
|  | $ignore = array_fuse($ignore); | ||||||
|  |  | ||||||
|  | $zones = $xml->windowsZones->mapTimezones->mapZone; | ||||||
|  | foreach ($zones as $zone) { | ||||||
|  |   $windows_name = (string)$zone['other']; | ||||||
|  |   $target_name = (string)$zone['type']; | ||||||
|  |  | ||||||
|  |   // Ignore the offset-based timezones from the CLDR map, since we handle | ||||||
|  |   // these later. | ||||||
|  |   if (isset($ignore[$windows_name])) { | ||||||
|  |     continue; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // We've already seen this timezone so we don't need to add it to the map | ||||||
|  |   // again. | ||||||
|  |   if (isset($result_map[$windows_name])) { | ||||||
|  |     continue; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $result_map[$windows_name] = $target_name; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | asort($result_map); | ||||||
|  |  | ||||||
|  | echo id(new PhutilJSON()) | ||||||
|  |   ->encodeFormatted($result_map); | ||||||
							
								
								
									
										126
									
								
								resources/timezones/windows-timezones.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,126 @@ | |||||||
|  | { | ||||||
|  |   "Egypt Standard Time": "Africa/Cairo", | ||||||
|  |   "Morocco Standard Time": "Africa/Casablanca", | ||||||
|  |   "South Africa Standard Time": "Africa/Johannesburg", | ||||||
|  |   "W. Central Africa Standard Time": "Africa/Lagos", | ||||||
|  |   "E. Africa Standard Time": "Africa/Nairobi", | ||||||
|  |   "Libya Standard Time": "Africa/Tripoli", | ||||||
|  |   "Namibia Standard Time": "Africa/Windhoek", | ||||||
|  |   "Aleutian Standard Time": "America/Adak", | ||||||
|  |   "Alaskan Standard Time": "America/Anchorage", | ||||||
|  |   "Tocantins Standard Time": "America/Araguaina", | ||||||
|  |   "Paraguay Standard Time": "America/Asuncion", | ||||||
|  |   "Bahia Standard Time": "America/Bahia", | ||||||
|  |   "SA Pacific Standard Time": "America/Bogota", | ||||||
|  |   "Argentina Standard Time": "America/Buenos_Aires", | ||||||
|  |   "Eastern Standard Time (Mexico)": "America/Cancun", | ||||||
|  |   "Venezuela Standard Time": "America/Caracas", | ||||||
|  |   "SA Eastern Standard Time": "America/Cayenne", | ||||||
|  |   "Central Standard Time": "America/Chicago", | ||||||
|  |   "Mountain Standard Time (Mexico)": "America/Chihuahua", | ||||||
|  |   "Central Brazilian Standard Time": "America/Cuiaba", | ||||||
|  |   "Mountain Standard Time": "America/Denver", | ||||||
|  |   "Greenland Standard Time": "America/Godthab", | ||||||
|  |   "Turks And Caicos Standard Time": "America/Grand_Turk", | ||||||
|  |   "Central America Standard Time": "America/Guatemala", | ||||||
|  |   "Atlantic Standard Time": "America/Halifax", | ||||||
|  |   "Cuba Standard Time": "America/Havana", | ||||||
|  |   "US Eastern Standard Time": "America/Indianapolis", | ||||||
|  |   "SA Western Standard Time": "America/La_Paz", | ||||||
|  |   "Pacific Standard Time": "America/Los_Angeles", | ||||||
|  |   "Central Standard Time (Mexico)": "America/Mexico_City", | ||||||
|  |   "Saint Pierre Standard Time": "America/Miquelon", | ||||||
|  |   "Montevideo Standard Time": "America/Montevideo", | ||||||
|  |   "Eastern Standard Time": "America/New_York", | ||||||
|  |   "US Mountain Standard Time": "America/Phoenix", | ||||||
|  |   "Haiti Standard Time": "America/Port-au-Prince", | ||||||
|  |   "Canada Central Standard Time": "America/Regina", | ||||||
|  |   "Pacific SA Standard Time": "America/Santiago", | ||||||
|  |   "E. South America Standard Time": "America/Sao_Paulo", | ||||||
|  |   "Newfoundland Standard Time": "America/St_Johns", | ||||||
|  |   "Pacific Standard Time (Mexico)": "America/Tijuana", | ||||||
|  |   "Central Asia Standard Time": "Asia/Almaty", | ||||||
|  |   "Jordan Standard Time": "Asia/Amman", | ||||||
|  |   "Arabic Standard Time": "Asia/Baghdad", | ||||||
|  |   "Azerbaijan Standard Time": "Asia/Baku", | ||||||
|  |   "SE Asia Standard Time": "Asia/Bangkok", | ||||||
|  |   "Altai Standard Time": "Asia/Barnaul", | ||||||
|  |   "Middle East Standard Time": "Asia/Beirut", | ||||||
|  |   "India Standard Time": "Asia/Calcutta", | ||||||
|  |   "Transbaikal Standard Time": "Asia/Chita", | ||||||
|  |   "Sri Lanka Standard Time": "Asia/Colombo", | ||||||
|  |   "Syria Standard Time": "Asia/Damascus", | ||||||
|  |   "Bangladesh Standard Time": "Asia/Dhaka", | ||||||
|  |   "Arabian Standard Time": "Asia/Dubai", | ||||||
|  |   "West Bank Standard Time": "Asia/Hebron", | ||||||
|  |   "W. Mongolia Standard Time": "Asia/Hovd", | ||||||
|  |   "North Asia East Standard Time": "Asia/Irkutsk", | ||||||
|  |   "Israel Standard Time": "Asia/Jerusalem", | ||||||
|  |   "Afghanistan Standard Time": "Asia/Kabul", | ||||||
|  |   "Russia Time Zone 11": "Asia/Kamchatka", | ||||||
|  |   "Pakistan Standard Time": "Asia/Karachi", | ||||||
|  |   "Nepal Standard Time": "Asia/Katmandu", | ||||||
|  |   "North Asia Standard Time": "Asia/Krasnoyarsk", | ||||||
|  |   "Magadan Standard Time": "Asia/Magadan", | ||||||
|  |   "N. Central Asia Standard Time": "Asia/Novosibirsk", | ||||||
|  |   "Omsk Standard Time": "Asia/Omsk", | ||||||
|  |   "North Korea Standard Time": "Asia/Pyongyang", | ||||||
|  |   "Myanmar Standard Time": "Asia/Rangoon", | ||||||
|  |   "Arab Standard Time": "Asia/Riyadh", | ||||||
|  |   "Sakhalin Standard Time": "Asia/Sakhalin", | ||||||
|  |   "Korea Standard Time": "Asia/Seoul", | ||||||
|  |   "China Standard Time": "Asia/Shanghai", | ||||||
|  |   "Singapore Standard Time": "Asia/Singapore", | ||||||
|  |   "Russia Time Zone 10": "Asia/Srednekolymsk", | ||||||
|  |   "Taipei Standard Time": "Asia/Taipei", | ||||||
|  |   "West Asia Standard Time": "Asia/Tashkent", | ||||||
|  |   "Georgian Standard Time": "Asia/Tbilisi", | ||||||
|  |   "Iran Standard Time": "Asia/Tehran", | ||||||
|  |   "Tokyo Standard Time": "Asia/Tokyo", | ||||||
|  |   "Tomsk Standard Time": "Asia/Tomsk", | ||||||
|  |   "Ulaanbaatar Standard Time": "Asia/Ulaanbaatar", | ||||||
|  |   "Vladivostok Standard Time": "Asia/Vladivostok", | ||||||
|  |   "Yakutsk Standard Time": "Asia/Yakutsk", | ||||||
|  |   "Ekaterinburg Standard Time": "Asia/Yekaterinburg", | ||||||
|  |   "Caucasus Standard Time": "Asia/Yerevan", | ||||||
|  |   "Azores Standard Time": "Atlantic/Azores", | ||||||
|  |   "Cape Verde Standard Time": "Atlantic/Cape_Verde", | ||||||
|  |   "Greenwich Standard Time": "Atlantic/Reykjavik", | ||||||
|  |   "Cen. Australia Standard Time": "Australia/Adelaide", | ||||||
|  |   "E. Australia Standard Time": "Australia/Brisbane", | ||||||
|  |   "AUS Central Standard Time": "Australia/Darwin", | ||||||
|  |   "Aus Central W. Standard Time": "Australia/Eucla", | ||||||
|  |   "Tasmania Standard Time": "Australia/Hobart", | ||||||
|  |   "Lord Howe Standard Time": "Australia/Lord_Howe", | ||||||
|  |   "W. Australia Standard Time": "Australia/Perth", | ||||||
|  |   "AUS Eastern Standard Time": "Australia/Sydney", | ||||||
|  |   "Dateline Standard Time": "Etc/GMT+12", | ||||||
|  |   "Astrakhan Standard Time": "Europe/Astrakhan", | ||||||
|  |   "W. Europe Standard Time": "Europe/Berlin", | ||||||
|  |   "GTB Standard Time": "Europe/Bucharest", | ||||||
|  |   "Central Europe Standard Time": "Europe/Budapest", | ||||||
|  |   "E. Europe Standard Time": "Europe/Chisinau", | ||||||
|  |   "Turkey Standard Time": "Europe/Istanbul", | ||||||
|  |   "Kaliningrad Standard Time": "Europe/Kaliningrad", | ||||||
|  |   "FLE Standard Time": "Europe/Kiev", | ||||||
|  |   "GMT Standard Time": "Europe/London", | ||||||
|  |   "Belarus Standard Time": "Europe/Minsk", | ||||||
|  |   "Russian Standard Time": "Europe/Moscow", | ||||||
|  |   "Romance Standard Time": "Europe/Paris", | ||||||
|  |   "Russia Time Zone 3": "Europe/Samara", | ||||||
|  |   "Central European Standard Time": "Europe/Warsaw", | ||||||
|  |   "Mauritius Standard Time": "Indian/Mauritius", | ||||||
|  |   "Samoa Standard Time": "Pacific/Apia", | ||||||
|  |   "New Zealand Standard Time": "Pacific/Auckland", | ||||||
|  |   "Bougainville Standard Time": "Pacific/Bougainville", | ||||||
|  |   "Chatham Islands Standard Time": "Pacific/Chatham", | ||||||
|  |   "Easter Island Standard Time": "Pacific/Easter", | ||||||
|  |   "Fiji Standard Time": "Pacific/Fiji", | ||||||
|  |   "Central Pacific Standard Time": "Pacific/Guadalcanal", | ||||||
|  |   "Hawaiian Standard Time": "Pacific/Honolulu", | ||||||
|  |   "Line Islands Standard Time": "Pacific/Kiritimati", | ||||||
|  |   "Marquesas Standard Time": "Pacific/Marquesas", | ||||||
|  |   "Norfolk Standard Time": "Pacific/Norfolk", | ||||||
|  |   "West Pacific Standard Time": "Pacific/Port_Moresby", | ||||||
|  |   "Tonga Standard Time": "Pacific/Tongatapu" | ||||||
|  | } | ||||||
							
								
								
									
										172
									
								
								scripts/auth_provider/auth_provider.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,172 @@ | |||||||
|  | #!/usr/local/bin/php | ||||||
|  | <?php | ||||||
|  | # | ||||||
|  | # ***** BEGIN GPL LICENSE BLOCK ***** | ||||||
|  | # | ||||||
|  | # This program is free software; you can redistribute it and/or | ||||||
|  | # modify it under the terms of the GNU General Public License | ||||||
|  | # as published by the Free Software Foundation; either version 2 | ||||||
|  | # of the License, or (at your option) any later version. | ||||||
|  | # | ||||||
|  | # This program is distributed in the hope that it will be useful, | ||||||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  | # GNU General Public License for more details. | ||||||
|  | # | ||||||
|  | # You should have received a copy of the GNU General Public License | ||||||
|  | # along with this program; if not, write to the Free Software Foundation, | ||||||
|  | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||||
|  | # | ||||||
|  | # The Original Code is Copyright (C) 2019, Blender Foundation | ||||||
|  | # All rights reserved. | ||||||
|  | # | ||||||
|  | # Contributor(s): Sergey Sharybin. | ||||||
|  | # | ||||||
|  | # ***** END GPL LICENSE BLOCK ***** | ||||||
|  | # | ||||||
|  | # This scripts implements external AuthBasicProvider which can be used | ||||||
|  | # to authentificate users using Phabricator's database. | ||||||
|  | # | ||||||
|  | # Example configuration: | ||||||
|  | # | ||||||
|  | # .htaccess file: | ||||||
|  | # | ||||||
|  | #   AuthType Basic | ||||||
|  | #   AuthName "Please Enter Password" | ||||||
|  | #   AuthBasicProvider external | ||||||
|  | #   AuthExternal phabricator | ||||||
|  | #   Require valid-user | ||||||
|  | # | ||||||
|  | # It is also required to have the following provider registered in the | ||||||
|  | # configuration. There are two ways to do it: | ||||||
|  | # | ||||||
|  | #  1. Separate conf file in /etc/apache2/conf-enabled | ||||||
|  | #     Create a file (say, authz_external_phabricator.conf) with the following | ||||||
|  | #     content: | ||||||
|  | # | ||||||
|  | #       DefineExternalAuth phabricator pipe /path/to/auth_provider.php | ||||||
|  | # | ||||||
|  | #     This method allows to use provider in any VHOST. | ||||||
|  | # | ||||||
|  | #     Downside: from local tests .htaccess file picks the provider nicely, | ||||||
|  | #     but attempts to specifu the provider in virtual host configuration | ||||||
|  | #     resulted in issues (seems to be different initialization order between | ||||||
|  | #     global config in those files and virtual hosts). | ||||||
|  | # | ||||||
|  | #  2. Define provider in the virtual host definition: | ||||||
|  | # | ||||||
|  | #       <IfModule mod_authnz_external.c> | ||||||
|  | #         AddExternalAuth phabricator /path/to/auth_provider.php | ||||||
|  | #         SetExternalAuthMethod phabricator pipe | ||||||
|  | #       </IfModule> | ||||||
|  | # | ||||||
|  | #     This method allowed to use this auth provider for SVN DAV. | ||||||
|  |  | ||||||
|  | $IS_DEBUG = false; | ||||||
|  | $PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__))); | ||||||
|  | require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php'; | ||||||
|  |  | ||||||
|  | function initLogging() { | ||||||
|  |   global $IS_DEBUG; | ||||||
|  |   global $argv; | ||||||
|  |   for ($i = 1; $i < count($argv); ++$i) { | ||||||
|  |     if ($argv[$i] == '--debug') { | ||||||
|  |       $IS_DEBUG = true; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function debugLog(string $text) { | ||||||
|  |   global $IS_DEBUG; | ||||||
|  |   if (!$IS_DEBUG) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   print("${text}\n"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function removeSingleTrailingNewline(string $string) { | ||||||
|  |   if ($string === '') { | ||||||
|  |     return $string; | ||||||
|  |   } | ||||||
|  |   $length = strlen($string); | ||||||
|  |   if ($string[$length - 1] == "\n") { | ||||||
|  |     return substr($string, 0, -1); | ||||||
|  |   } | ||||||
|  |   return $string; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class AuthRequest { | ||||||
|  |   public $user_name; | ||||||
|  |   public $password; | ||||||
|  |  | ||||||
|  |   static function fromStdin() { | ||||||
|  |     $auth_request = new AuthRequest(); | ||||||
|  |     $stdin = fopen('php://stdin', 'r'); | ||||||
|  |     $auth_request->user_name = removeSingleTrailingNewline(fgets($stdin)); | ||||||
|  |     $auth_request->password = removeSingleTrailingNewline(fgets($stdin)); | ||||||
|  |     return $auth_request; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function getUserForAuthRequest(AuthRequest $auth_request) { | ||||||
|  |   if ($auth_request->user_name === '') { | ||||||
|  |     return null; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $username_or_email = $auth_request->user_name; | ||||||
|  |  | ||||||
|  |   $user = id(new PhabricatorUser())->loadOneWhere( | ||||||
|  |     'username = %s', | ||||||
|  |     $username_or_email); | ||||||
|  |  | ||||||
|  |   if (!$user) { | ||||||
|  |     $user = PhabricatorUser::loadOneWithEmailAddress( | ||||||
|  |     $username_or_email); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return $user; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function createContentSourceForAuth() { | ||||||
|  |   return PhabricatorContentSource::newForSource( | ||||||
|  |       PhabricatorUnitTestContentSource::SOURCECONST); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function isValidAuth(AuthRequest $auth_request) { | ||||||
|  |   debugLog("Begin authentification check for user '$auth_request->user_name'"); | ||||||
|  |   $user = getUserForAuthRequest($auth_request); | ||||||
|  |   if (!$user) { | ||||||
|  |     debugLog("No PhabricatorUser() object found for requested user."); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $content_source = createContentSourceForAuth(); | ||||||
|  |   $envelope = new PhutilOpaqueEnvelope($auth_request->password); | ||||||
|  |  | ||||||
|  |   $engine = id(new PhabricatorAuthPasswordEngine()) | ||||||
|  |       ->setViewer($user) | ||||||
|  |       ->setContentSource($content_source) | ||||||
|  |       ->setPasswordType(PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT) | ||||||
|  |       ->setObject($user); | ||||||
|  |  | ||||||
|  |   if (!$engine->isValidPassword($envelope)) { | ||||||
|  |     debugLog('Engine reported invalid password.'); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   debugLog('Authentirfication passed.'); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function main() { | ||||||
|  |   initLogging(); | ||||||
|  |   $auth_request = AuthRequest::fromStdin(); | ||||||
|  |   if (!isValidAuth($auth_request)) { | ||||||
|  |     exit(1); | ||||||
|  |   } | ||||||
|  |   exit(0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | main(); | ||||||
|  | ?> | ||||||
							
								
								
									
										131
									
								
								scripts/daemon/exec/exec_daemon.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,131 @@ | |||||||
|  | #!/usr/bin/env php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | if (function_exists('pcntl_async_signals')) { | ||||||
|  |   pcntl_async_signals(true); | ||||||
|  | } else { | ||||||
|  |   declare(ticks = 1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | require_once dirname(__FILE__).'/../../__init_script__.php'; | ||||||
|  |  | ||||||
|  | if (!posix_isatty(STDOUT)) { | ||||||
|  |   $sid = posix_setsid(); | ||||||
|  |   if ($sid <= 0) { | ||||||
|  |     throw new Exception(pht('Failed to create new process session!')); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $args = new PhutilArgumentParser($argv); | ||||||
|  | $args->setTagline(pht('daemon executor')); | ||||||
|  | $args->setSynopsis(<<<EOHELP | ||||||
|  | **exec_daemon.php** [__options__] __daemon__ ... | ||||||
|  |     Run an instance of __daemon__. | ||||||
|  | EOHELP | ||||||
|  |   ); | ||||||
|  | $args->parse( | ||||||
|  |   array( | ||||||
|  |     array( | ||||||
|  |       'name' => 'trace', | ||||||
|  |       'help' => pht('Enable debug tracing.'), | ||||||
|  |     ), | ||||||
|  |     array( | ||||||
|  |       'name' => 'trace-memory', | ||||||
|  |       'help' => pht('Enable debug memory tracing.'), | ||||||
|  |     ), | ||||||
|  |     array( | ||||||
|  |       'name' => 'verbose', | ||||||
|  |       'help'  => pht('Enable verbose activity logging.'), | ||||||
|  |     ), | ||||||
|  |     array( | ||||||
|  |       'name' => 'label', | ||||||
|  |       'short' => 'l', | ||||||
|  |       'param' => 'label', | ||||||
|  |       'help' => pht( | ||||||
|  |         'Optional process label. Makes "%s" nicer, no behavioral effects.', | ||||||
|  |         'ps'), | ||||||
|  |     ), | ||||||
|  |     array( | ||||||
|  |       'name'     => 'daemon', | ||||||
|  |       'wildcard' => true, | ||||||
|  |     ), | ||||||
|  |   )); | ||||||
|  |  | ||||||
|  | $trace_memory = $args->getArg('trace-memory'); | ||||||
|  | $trace_mode = $args->getArg('trace') || $trace_memory; | ||||||
|  | $verbose = $args->getArg('verbose'); | ||||||
|  |  | ||||||
|  | if (function_exists('posix_isatty') && posix_isatty(STDIN)) { | ||||||
|  |   fprintf(STDERR, pht('Reading daemon configuration from stdin...')."\n"); | ||||||
|  | } | ||||||
|  | $config = @file_get_contents('php://stdin'); | ||||||
|  | $config = id(new PhutilJSONParser())->parse($config); | ||||||
|  |  | ||||||
|  | PhutilTypeSpec::checkMap( | ||||||
|  |   $config, | ||||||
|  |   array( | ||||||
|  |     'log' => 'optional string|null', | ||||||
|  |     'argv' => 'optional list<wild>', | ||||||
|  |     'load' => 'optional list<string>', | ||||||
|  |     'down' => 'optional int', | ||||||
|  |   )); | ||||||
|  |  | ||||||
|  | $log = idx($config, 'log'); | ||||||
|  |  | ||||||
|  | if ($log) { | ||||||
|  |   ini_set('error_log', $log); | ||||||
|  |   PhutilErrorHandler::setErrorListener(array('PhutilDaemon', 'errorListener')); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $load = idx($config, 'load', array()); | ||||||
|  | foreach ($load as $library) { | ||||||
|  |   $library = Filesystem::resolvePath($library); | ||||||
|  |   phutil_load_library($library); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | PhutilErrorHandler::initialize(); | ||||||
|  |  | ||||||
|  | $daemon = $args->getArg('daemon'); | ||||||
|  | if (!$daemon) { | ||||||
|  |   throw new PhutilArgumentUsageException( | ||||||
|  |     pht('Specify which class of daemon to start.')); | ||||||
|  | } else if (count($daemon) > 1) { | ||||||
|  |   throw new PhutilArgumentUsageException( | ||||||
|  |     pht('Specify exactly one daemon to start.')); | ||||||
|  | } else { | ||||||
|  |   $daemon = head($daemon); | ||||||
|  |   if (!class_exists($daemon)) { | ||||||
|  |     throw new PhutilArgumentUsageException( | ||||||
|  |       pht( | ||||||
|  |         'No class "%s" exists in any known library.', | ||||||
|  |         $daemon)); | ||||||
|  |   } else if (!is_subclass_of($daemon, 'PhutilDaemon')) { | ||||||
|  |     throw new PhutilArgumentUsageException( | ||||||
|  |       pht( | ||||||
|  |         'Class "%s" is not a subclass of "%s".', | ||||||
|  |         $daemon, | ||||||
|  |         'PhutilDaemon')); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $argv = idx($config, 'argv', array()); | ||||||
|  | $daemon = newv($daemon, array($argv)); | ||||||
|  |  | ||||||
|  | if ($trace_mode) { | ||||||
|  |   $daemon->setTraceMode(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if ($trace_memory) { | ||||||
|  |   $daemon->setTraceMemory(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if ($verbose) { | ||||||
|  |   $daemon->setVerbose(true); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $down_duration = idx($config, 'down'); | ||||||
|  | if ($down_duration) { | ||||||
|  |   $daemon->setScaledownDuration($down_duration); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $daemon->execute(); | ||||||
							
								
								
									
										6
									
								
								scripts/gitadmin/gitx-ssh
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,6 @@ | |||||||
|  | #!/usr/local/bin/bash | ||||||
|  |  | ||||||
|  | set -e | ||||||
|  | set -u | ||||||
|  |  | ||||||
|  | ssh -i $SSH_KEYFILE $@ | ||||||
							
								
								
									
										443
									
								
								scripts/gitadmin/rebuild_gitadmin.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,443 @@ | |||||||
|  | #!/usr/local/bin/php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $root = dirname(dirname(dirname(__FILE__))); | ||||||
|  | require_once $root.'/scripts/__init_script__.php'; | ||||||
|  |  | ||||||
|  | function escape_name($name) { | ||||||
|  |   return preg_replace('/[^A-Za-z0-9\-]/', '_', $name); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function startswith($string, $prefix) { | ||||||
|  |   return substr($string, 0, strlen($prefix)) == $prefix; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function endswith($string, $suffix) { | ||||||
|  |   $suffix_length = strlen($suffix); | ||||||
|  |   return substr($string, strlen($string) - $suffix_length, | ||||||
|  |                 $suffix_length) == $suffix; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function write_ini_file($array, $file) { | ||||||
|  |   $res = array(); | ||||||
|  |   foreach ($array as $key => $val) { | ||||||
|  |     if (is_array($val)) { | ||||||
|  |       $res[] = "[$key]"; | ||||||
|  |       foreach ($val as $skey => $sval) { | ||||||
|  |         $res[] = "$skey = $sval"; | ||||||
|  |       } | ||||||
|  |       $res[] = ''; | ||||||
|  |     } else { | ||||||
|  |       $res[] = "$key = $val"; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   file_put_contents($file, implode("\n", $res)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getProjectMembersPHIDs($viewer, $project_phid) { | ||||||
|  |   $project = id(new PhabricatorProjectQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->needMembers(true) | ||||||
|  |     ->withPHIDs(array($project_phid)) | ||||||
|  |     ->executeOne(); | ||||||
|  |  | ||||||
|  |   return $project->getMemberPHIDs(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get user's heys and put them to the configuration | ||||||
|  | function handleSingleUserPHID( | ||||||
|  |   $keydir, $viewer, $userPHID, $system_keys, &$used_keys) { | ||||||
|  |   $user = id(new PhabricatorPeopleQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withPHIDs(array($userPHID)) | ||||||
|  |     ->executeOne(); | ||||||
|  |   if (!$user) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ($user->getIsDisabled()) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $keys = id(new PhabricatorAuthSSHKey())->loadAllWhere( | ||||||
|  |    'objectPHID = %s', | ||||||
|  |     $user->getPHID()); | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($keys as $key) { | ||||||
|  |       $full_key_content = | ||||||
|  |         $key->getKeyType().' '. | ||||||
|  |         $key->getKeyBody().' '. | ||||||
|  |         $key->getKeyComment()."\n"; | ||||||
|  |  | ||||||
|  |     if (array_key_exists($full_key_content, $system_keys)) { | ||||||
|  |       $members[] = $system_keys[$full_key_content]; | ||||||
|  |     } else { | ||||||
|  |       $escaped_key_name = escape_name($key->getName()); | ||||||
|  |       $member = 'PHAB_'.$user->getUserName(). | ||||||
|  |         '_'.$escaped_key_name. | ||||||
|  |         '_'.$key->getID(); | ||||||
|  |       $members[] = $member; | ||||||
|  |       if (!array_key_exists($member, $used_keys)) { | ||||||
|  |         $used_keys[$member] = true; | ||||||
|  |         file_put_contents("$keydir/$member.pub", $full_key_content); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleUsersPolicyRule( | ||||||
|  |   $keydir, $viewer, $rule, $system_keys, &$used_keys) { | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($rule['value'] as $userPHID) { | ||||||
|  |     $members = array_merge($members, | ||||||
|  |       handleSingleUserPHID($keydir, $viewer, $userPHID, | ||||||
|  |                            $system_keys, $used_keys)); | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsPolicyRule( | ||||||
|  |   $keydir, $viewer, $rule, $system_keys, &$used_keys) { | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($rule['value'] as $projectPHID) { | ||||||
|  |     $memberPHIDs = getProjectMembersPHIDs($viewer, $projectPHID); | ||||||
|  |     foreach ($memberPHIDs as $userPHID) { | ||||||
|  |       $members = array_merge($members, | ||||||
|  |         handleSingleUserPHID($keydir, $viewer, $userPHID, | ||||||
|  |                              $system_keys, $used_keys)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsAllPolicyRule( | ||||||
|  |   $keydir, $viewer, $rule, $system_keys, &$used_keys) { | ||||||
|  |   $is_first_project = true; | ||||||
|  |   $allowed_members_phids = array(); | ||||||
|  |   foreach ($rule['value'] as $project_phid) { | ||||||
|  |     $memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid); | ||||||
|  |     if ($is_first_project) { | ||||||
|  |       $allowed_members_phids = $memberPHIDs; | ||||||
|  |       $is_first_project = false; | ||||||
|  |     } else { | ||||||
|  |       $allowed_members_phids = array_intersect( | ||||||
|  |         $allowed_members_phids, $memberPHIDs); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($allowed_members_phids as $userPHID) { | ||||||
|  |     $members = array_merge($members, | ||||||
|  |       handleSingleUserPHID($keydir, $viewer, $userPHID, | ||||||
|  |                            $system_keys, $used_keys)); | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleAdministratorsPolicyRule( | ||||||
|  |   $keydir, $viewer, $rule, $system_keys, &$used_keys) { | ||||||
|  |   $administrators = id(new PhabricatorPeopleQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withIsAdmin(true) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($administrators as $administrator) { | ||||||
|  |     $members = array_merge($members, | ||||||
|  |       handleSingleUserPHID($keydir, $viewer, $administrator->getPHID(), | ||||||
|  |                            $system_keys, $used_keys)); | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSingleDocument( | ||||||
|  |   $keydir, $viewer, $document, $system_keys, &$used_keys) { | ||||||
|  |   if ($document->getSignatureType() != | ||||||
|  |       LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($document->getSignatures() as $signature) { | ||||||
|  |     if ($signature->getSignatureType() != | ||||||
|  |         LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |     $members = array_merge($members, | ||||||
|  |       handleSingleUserPHID($keydir, $viewer, $signature->getSignerPHID(), | ||||||
|  |                            $system_keys, $used_keys)); | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSignaturePolicyRule( | ||||||
|  |   $keydir, $viewer, $rule, $system_keys, &$used_keys) { | ||||||
|  |   $documents = id(new LegalpadDocumentQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withPHIDs($rule['value']) | ||||||
|  |     ->needSignatures(true) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |   foreach ($documents as $document) { | ||||||
|  |     $members = array_merge( | ||||||
|  |       $members, | ||||||
|  |       handleLegalpadSingleDocument( | ||||||
|  |         $keydir, $viewer, $document, $system_keys, $used_keys)); | ||||||
|  |   } | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleCustomPolicy( | ||||||
|  |   $keydir, $viewer, $policy, $system_keys, &$used_keys) { | ||||||
|  |   $members = array(); | ||||||
|  |   $rules = $policy->getRules(); | ||||||
|  |   foreach ($rules as $rule) { | ||||||
|  |     // Everyone is denied by default anyway | ||||||
|  |     if ($rule['action'] != 'allow') { | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $policy_members = array(); | ||||||
|  |     $rule_type = $rule['rule']; | ||||||
|  |     if ($rule_type == 'PhabricatorPolicyRuleUsers') { | ||||||
|  |       $policy_members = handleUsersPolicyRule( | ||||||
|  |         $keydir, $viewer, $rule, $system_keys, $used_keys); | ||||||
|  |     } else if ($rule_type == 'PhabricatorProjectsPolicyRule') { | ||||||
|  |       $policy_members = handleProjectsPolicyRule( | ||||||
|  |         $keydir, $viewer, $rule, $system_keys, $used_keys); | ||||||
|  |     } else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') { | ||||||
|  |       $policy_members = handleProjectsAllPolicyRule( | ||||||
|  |         $keydir, $viewer, $rule, $system_keys, $used_keys); | ||||||
|  |     } else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') { | ||||||
|  |       $policy_members = handleAdministratorsPolicyRule( | ||||||
|  |         $keydir, $viewer, $rule, $system_keys, $used_keys); | ||||||
|  |     } else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') { | ||||||
|  |       $policy_members = handleLegalpadSignaturePolicyRule( | ||||||
|  |         $keydir, $viewer, $rule, $system_keys, $used_keys); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $members = array_merge($members, $policy_members); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return $members; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Parse repository and put it's members to the config file | ||||||
|  | function handleSingleRepository( | ||||||
|  |   $keydir, $viewer, $repository, $all_repositories, $system_keys, | ||||||
|  |   &$new_configuration, &$used_keys) { | ||||||
|  |   $policies = PhabricatorPolicyQuery::loadPolicies( | ||||||
|  |     $viewer, | ||||||
|  |     $repository); | ||||||
|  |  | ||||||
|  |   $pushable = $policies[DiffusionPushCapability::CAPABILITY]; | ||||||
|  |   $type = $pushable->getType(); | ||||||
|  |  | ||||||
|  |   $members = array(); | ||||||
|  |  | ||||||
|  |   if ($type == PhabricatorPolicyType::TYPE_PROJECT) { | ||||||
|  |     $project = id(new PhabricatorProjectQuery()) | ||||||
|  |       ->setViewer($viewer) | ||||||
|  |       ->needMembers(true) | ||||||
|  |       ->withPHIDs(array($pushable->getPHID())) | ||||||
|  |       ->executeOne(); | ||||||
|  |  | ||||||
|  |     $memberPHIDs = $project->getMemberPHIDs(); | ||||||
|  |     foreach ($memberPHIDs as $memberPHID) { | ||||||
|  |       $members = array_merge($members, | ||||||
|  |         handleSingleUserPHID($keydir, $viewer, $memberPHID, | ||||||
|  |                              $system_keys, $used_keys)); | ||||||
|  |     } | ||||||
|  |   } else if ($type == PhabricatorPolicyType::TYPE_USER) { | ||||||
|  |     $members = handleSingleUserPHID( | ||||||
|  |       $keydir, $viewer, $pushable->getPHID(), $system_keys, $used_keys); | ||||||
|  |   } else if ($type == PhabricatorPolicyType::TYPE_CUSTOM) { | ||||||
|  |     $members = handleCustomPolicy( | ||||||
|  |       $keydir, $viewer, $pushable, $system_keys, $used_keys); | ||||||
|  |   } else { | ||||||
|  |     /* pass */ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (count($members)) { | ||||||
|  |     $uri = $repository->getRemoteURI(); | ||||||
|  |     $repository_name = basename($uri, '.git'); | ||||||
|  |     $escaped_repository_name = escape_name($repository->getName()); | ||||||
|  |     $group_name = "PHAB_${escaped_repository_name}"; | ||||||
|  |     $values = array(); | ||||||
|  |     $values['members'] = join(' ', $members); | ||||||
|  |     $values['readonly'] = join(' ', $all_repositories); | ||||||
|  |     $values['writable'] = $repository_name; | ||||||
|  |     $new_configuration["group $group_name"] = $values; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Remove groups from previous automated configuration built | ||||||
|  | function getCleanOldConfiguration($old_configuration) { | ||||||
|  |   $new_configuration = array(); | ||||||
|  |   foreach ($old_configuration as $group => $values) { | ||||||
|  |     if (!startswith($group, 'group PHAB')) { | ||||||
|  |       $new_configuration[$group] = $values; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return $new_configuration; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get non-phab keys | ||||||
|  | function getSystemPublicKeys($keydir) { | ||||||
|  |   $files = scandir($keydir); | ||||||
|  |   $system_keys = array(); | ||||||
|  |   foreach ($files as $file) { | ||||||
|  |     if (!startswith($file, "PHAB") && endswith($file, '.pub')) { | ||||||
|  |       $key = file_get_contents("$keydir/$file"); | ||||||
|  |       $system_keys[$key] = basename($file, '.pub'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return $system_keys; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Remove unused public keys | ||||||
|  | function removeUnusedPublicKeys($keydir, $used_keys) { | ||||||
|  |   $files = scandir($keydir); | ||||||
|  |   foreach ($files as $file) { | ||||||
|  |     if (startswith($file, "PHAB")) { | ||||||
|  |       $member = basename($file, '.pub'); | ||||||
|  |       if (!array_key_exists($member, $used_keys)) { | ||||||
|  |         unlink("$keydir/$file"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function rebuildConfiguration($gitosis_root) { | ||||||
|  |   $keydir = "$gitosis_root/keydir"; | ||||||
|  |   $configuration_file = "$gitosis_root/gitosis.conf"; | ||||||
|  |  | ||||||
|  |   if (!file_exists($configuration_file)) { | ||||||
|  |     print("Not found: $configuration_file\n"); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $viewer = id(new PhabricatorUser()) | ||||||
|  |     ->loadOneWhere('username = %s', 'sergey'); | ||||||
|  |  | ||||||
|  |   $old_configuration = parse_ini_file( | ||||||
|  |     $configuration_file, true, INI_SCANNER_RAW); | ||||||
|  |  | ||||||
|  |   $new_configuration = getCleanOldConfiguration( | ||||||
|  |     $old_configuration); | ||||||
|  |  | ||||||
|  |   // Get "system" keys to re-use if phab account uses the | ||||||
|  |   // same public key | ||||||
|  |   $system_keys = getSystemPublicKeys($keydir); | ||||||
|  |  | ||||||
|  |   // Get list of all repos which is awailable for read | ||||||
|  |   $all_repositories = array(); | ||||||
|  |   foreach ($old_configuration as $group => $values) { | ||||||
|  |     if (startswith($group, 'repo')) { | ||||||
|  |       $repository_name = substr($group, 5, strlen($group) - 5); | ||||||
|  |       if ($repository_name == 'gitosis-admin') | ||||||
|  |         continue; | ||||||
|  |       $all_repositories[] = $repository_name; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Fill in new configuration and keys | ||||||
|  |   $used_keys = array(); | ||||||
|  |   $repositories = id(new PhabricatorRepositoryQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   foreach ($repositories as $repository_id => $repository) { | ||||||
|  |     $type = $repository->getVersionControlSystem(); | ||||||
|  |     if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { | ||||||
|  |       handleSingleRepository( | ||||||
|  |         $keydir, $viewer, $repository, $all_repositories, $system_keys, | ||||||
|  |         $new_configuration, $used_keys); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   write_ini_file($new_configuration, $configuration_file); | ||||||
|  |   removeUnusedPublicKeys($keydir, $used_keys); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getGitCommand($repository) { | ||||||
|  |   $git_dir = realpath("$repository/.git"); | ||||||
|  |   $git = "git --git-dir='$git_dir'"; | ||||||
|  |   $git .= ' --work-tree='.realpath($repository); | ||||||
|  |   return $git; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function runGitCommand($repository, $arguments, | ||||||
|  |                        &$output=null, &$return_var=null) { | ||||||
|  |   $git = getGitCommand($repository); | ||||||
|  |   $git .= " $arguments"; | ||||||
|  |   exec($git, $output, $return_var); | ||||||
|  |   return $return_var == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function runGitSshCommand($repository, $key, $arguments, | ||||||
|  |                        &$output=null, &$return_var=null) { | ||||||
|  |   $gitx_ssh = realpath(dirname(__FILE__) . "/gitx-ssh"); | ||||||
|  |   $abs_key = realpath($key); | ||||||
|  |   $git = "SSH_KEYFILE=$abs_key GIT_SSH=$gitx_ssh "; | ||||||
|  |   $git .= getGitCommand($repository); | ||||||
|  |   $git .= " $arguments"; | ||||||
|  |   exec($git, $output, $return_var); | ||||||
|  |   return $return_var == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function repositoryPull($repository, $key) { | ||||||
|  |   return runGitSshCommand($repository, $key, 'pull'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function repositoryCommitAll($repository, $author, $message) { | ||||||
|  |   if (!runGitCommand( | ||||||
|  |     $repository, 'ls-files --other --exclude-standard', $untracked_files)) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   if (count($untracked_files)) { | ||||||
|  |     $flat_files = join(' ', $untracked_files); | ||||||
|  |     if (!runGitCommand($repository, "add $flat_files")) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   runGitCommand($repository, "update-index -q --refresh", $output); | ||||||
|  |   runGitCommand($repository, "diff-index --name-only HEAD --", $output); | ||||||
|  |   if (count($output)) { | ||||||
|  |     return runGitCommand( | ||||||
|  |       $repository, "commit --author='$author' -a -m '$message'", $output); | ||||||
|  |   } | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (count($argv) != 3) { | ||||||
|  |   print("Usage: {$argv[0]} /path/to/gitosis-admin /path/to/id_rsa.pub\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $gitosis_root = $argv[1]; | ||||||
|  | $key = $argv[2]; | ||||||
|  |  | ||||||
|  | if (!repositoryPull($gitosis_root, $key)) { | ||||||
|  |   print("Failed to pull changes from server.\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!rebuildConfiguration($gitosis_root)) { | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!repositoryCommitAll( | ||||||
|  |   $gitosis_root, 'Rebuild Gitadmin <null@git.blender.org>', | ||||||
|  |   'Update to correspond changes in Phabricator')) { | ||||||
|  |   print("Failed to commit changes.\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | runGitSshCommand($gitosis_root, $key, 'push origin master'); | ||||||
|  | ?> | ||||||
							
								
								
									
										504
									
								
								scripts/gitolite/rebuild_gitolite.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,504 @@ | |||||||
|  | #!/usr/local/bin/php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $root = dirname(dirname(dirname(__FILE__))); | ||||||
|  | require_once $root.'/scripts/__init_script__.php'; | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // Utilities. | ||||||
|  | // | ||||||
|  | // TODO(sergey): Move somewhere else. Or, evenmore ideally, use Phabricator's | ||||||
|  | // utilities instead. | ||||||
|  |  | ||||||
|  | function escape_name($name) { | ||||||
|  |   return preg_replace('/[^A-Za-z0-9]/', '_', $name); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function startswith($string, $prefix) { | ||||||
|  |   return substr($string, 0, strlen($prefix)) == $prefix; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function endswith($string, $suffix) { | ||||||
|  |   $suffix_length = strlen($suffix); | ||||||
|  |   return substr($string, strlen($string) - $suffix_length, | ||||||
|  |                 $suffix_length) == $suffix; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function file_put_contents_if_different($file_name, $content) { | ||||||
|  |   if (file_exists($file_name)) { | ||||||
|  |     $current_content = file_get_contents($file_name); | ||||||
|  |     if ($current_content == $content) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   file_put_contents($file_name, $content); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // Phabricator access list traversal. | ||||||
|  |  | ||||||
|  | class Configuration { | ||||||
|  |   // Phabricator user which is used as a viewer. | ||||||
|  |   public $viewer; | ||||||
|  |  | ||||||
|  |   // Directory where public keys are stored. | ||||||
|  |   // Full path. | ||||||
|  |   protected $keys_directory; | ||||||
|  |  | ||||||
|  |   // Gitolite configuration file (gitolite.conf). | ||||||
|  |   // Full path. | ||||||
|  |   protected $config_file; | ||||||
|  |  | ||||||
|  |   // Indexed by key content, contains configuration user name. | ||||||
|  |   protected $stored_keys; | ||||||
|  |  | ||||||
|  |   // Indexed by config user name. | ||||||
|  |   protected $used_keys; | ||||||
|  |  | ||||||
|  |   // Indexed by committers variable name, contains list of users which are | ||||||
|  |   // configured by Phabricator to be able to commit to the repository. | ||||||
|  |   protected $committers; | ||||||
|  |  | ||||||
|  |   public function __construct($gitolite_root) { | ||||||
|  |     $this->viewer = PhabricatorUser::getOmnipotentUser(); | ||||||
|  |     $this->keys_directory = "$gitolite_root/keydir"; | ||||||
|  |     $this->config_file = "$gitolite_root/conf/gitolite.conf"; | ||||||
|  |  | ||||||
|  |     $this->collectSystemPublicKeys(); | ||||||
|  |  | ||||||
|  |     $this->used_keys = array(); | ||||||
|  |     $this->committers = array(); | ||||||
|  |  | ||||||
|  |     if (!file_exists($this->config_file)) { | ||||||
|  |       die("Not found: $this->config_file\n"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Store given key of given user. | ||||||
|  |   // | ||||||
|  |   // Includes both storing public key in the file, and storing mapping between | ||||||
|  |   // user and the key. | ||||||
|  |   public function storeUserPublicKey($user, $key) { | ||||||
|  |     $full_key_content = $this->getPublicKeyContent($key); | ||||||
|  |  | ||||||
|  |     if (array_key_exists($full_key_content, $this->stored_keys)) { | ||||||
|  |       return $this->stored_keys[$full_key_content]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $config_user_name = $this->getConfigUserName($user, $key); | ||||||
|  |  | ||||||
|  |     if (!array_key_exists($config_user_name, $this->used_keys)) { | ||||||
|  |       $this->used_keys[$config_user_name] = true; | ||||||
|  |       file_put_contents_if_different("$this->keys_directory/$config_user_name.pub", | ||||||
|  |                                      $full_key_content); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->stored_keys[$full_key_content] = $config_user_name; | ||||||
|  |  | ||||||
|  |     return $config_user_name; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setRepositoryUsers($repository, $config_user_names) { | ||||||
|  |     $uri = $repository->getRemoteURI(); | ||||||
|  |     $repository_name = basename($uri, '.git'); | ||||||
|  |  | ||||||
|  |     $variable_name = '@committers_' . escape_name(strtolower($repository_name)); | ||||||
|  |  | ||||||
|  |     if (array_key_exists($variable_name, $this->committers)) { | ||||||
|  |       die("Duplicate variable mapping for repository $uri\n"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->committers[$variable_name] = $config_user_names; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function writeNewConfiguration() { | ||||||
|  |     $current_config = file_get_contents($this->config_file); | ||||||
|  |     $current_config_lines = explode("\n", $current_config); | ||||||
|  |  | ||||||
|  |     $new_config = ""; | ||||||
|  |     foreach ($current_config_lines as $line) { | ||||||
|  |       if (startswith($line, '@committers_')) { | ||||||
|  |         $parts = explode('=', $line); | ||||||
|  |         $variable_name = trim($parts[0]); | ||||||
|  |         if (array_key_exists($variable_name, $this->committers)) { | ||||||
|  |           $system_committers = $this->getNonPhabtricatorUsers($parts[1]); | ||||||
|  |           $all_committers = array_merge( | ||||||
|  |               $system_committers, $this->committers[$variable_name]); | ||||||
|  |           $unique_committers = array_unique($all_committers); | ||||||
|  |           $committers = implode(' ', $unique_committers); | ||||||
|  |           $line = "$variable_name = $committers"; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       $new_config .= $line . "\n"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     file_put_contents_if_different($this->config_file, trim($new_config) . "\n"); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function getNonPhabtricatorUsers($configuration_value) { | ||||||
|  |     $system_users = array(); | ||||||
|  |     $users = explode(' ', $configuration_value); | ||||||
|  |     foreach ($users as $user) { | ||||||
|  |       $user = trim($user); | ||||||
|  |       if (empty($user)) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  |       if (startswith($user, 'PHAB')) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  |       $system_users[] = $user; | ||||||
|  |     } | ||||||
|  |     return $system_users; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function finalize() { | ||||||
|  |     $this->removeUnusedPublicKeys(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Get content of a public key to be stored in file. | ||||||
|  |   protected function getPublicKeyContent($key) { | ||||||
|  |     return $key->getKeyType().' '. | ||||||
|  |            $key->getKeyBody().' '. | ||||||
|  |            $key->getKeyComment()."\n"; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Get user+key name used by the Gitolite configuration. | ||||||
|  |   protected function getConfigUserName($user, $key) { | ||||||
|  |     $escaped_key_name = escape_name($key->getName()); | ||||||
|  |     return 'PHAB_'.$user->getUserName(). | ||||||
|  |            '_'.$escaped_key_name. | ||||||
|  |            '_'.$key->getID(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Get keys which are not managed by this Phabricator/Git integration script. | ||||||
|  |   // | ||||||
|  |   // Returns map from key content to the key file name. This is used to avoid | ||||||
|  |   // public key duplication in the case system key is used by phabricator user. | ||||||
|  |   protected function collectSystemPublicKeys() { | ||||||
|  |     $files = scandir($this->keys_directory); | ||||||
|  |     foreach ($files as $file) { | ||||||
|  |       if (startswith($file, "PHAB")) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  |       if (!endswith($file, '.pub')) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  |       $key = file_get_contents("$this->keys_directory/$file"); | ||||||
|  |       $file_we = basename($file, '.pub'); | ||||||
|  |       $this->stored_keys[$key] = $file_we; | ||||||
|  |       $this->used_keys[$file_we] = true; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function removeUnusedPublicKeys() { | ||||||
|  |     $files = scandir($this->keys_directory); | ||||||
|  |     foreach ($files as $file) { | ||||||
|  |       if (!startswith($file, "PHAB")) { | ||||||
|  |         continue; | ||||||
|  |       } | ||||||
|  |       $config_user_name = basename($file, '.pub'); | ||||||
|  |       if (!array_key_exists($config_user_name, $this->used_keys)) { | ||||||
|  |         unlink("$this->keys_directory/$file"); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | function getProjectMembersPHIDs($viewer, $project_phid) { | ||||||
|  |   $project = id(new PhabricatorProjectQuery()) | ||||||
|  |       ->setViewer($viewer) | ||||||
|  |       ->needMembers(true) | ||||||
|  |       ->withPHIDs(array($project_phid)) | ||||||
|  |       ->executeOne(); | ||||||
|  |  | ||||||
|  |   return $project->getMemberPHIDs(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get user's heys and put them to the configuration | ||||||
|  | function handleSingleUserPHID($config, $userPHID) { | ||||||
|  |   $user = id(new PhabricatorPeopleQuery()) | ||||||
|  |     ->setViewer($config->viewer) | ||||||
|  |     ->withPHIDs(array($userPHID)) | ||||||
|  |     ->executeOne(); | ||||||
|  |   if (!$user) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ($user->getIsDisabled()) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $keys = id(new PhabricatorAuthSSHKey())->loadAllWhere( | ||||||
|  |    'objectPHID = %s', | ||||||
|  |     $user->getPHID()); | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($keys as $key) { | ||||||
|  |     $config_user_name = $config->storeUserPublicKey($user, $key); | ||||||
|  |     $config_user_names[] = $config_user_name; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleUsersPolicyRule($config, $rule) { | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($rule['value'] as $userPHID) { | ||||||
|  |     $config_user_names = array_merge($config_user_names, | ||||||
|  |       handleSingleUserPHID($config, $userPHID)); | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsPolicyRule($config, $rule) { | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($rule['value'] as $projectPHID) { | ||||||
|  |     $memberPHIDs = getProjectMembersPHIDs($config->viewer, $projectPHID); | ||||||
|  |     foreach ($memberPHIDs as $userPHID) { | ||||||
|  |       $config_user_names = array_merge($config_user_names, | ||||||
|  |         handleSingleUserPHID($config, $userPHID)); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsAllPolicyRule($config, $rule) { | ||||||
|  |   $is_first_project = true; | ||||||
|  |   $allowed_members_phids = array(); | ||||||
|  |   foreach ($rule['value'] as $project_phid) { | ||||||
|  |     $memberPHIDs = getProjectMembersPHIDs($config->viewer, $project_phid); | ||||||
|  |     if ($is_first_project) { | ||||||
|  |       $allowed_members_phids = $memberPHIDs; | ||||||
|  |       $is_first_project = false; | ||||||
|  |     } else { | ||||||
|  |       $allowed_members_phids = array_intersect( | ||||||
|  |         $allowed_members_phids, $memberPHIDs); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($allowed_members_phids as $userPHID) { | ||||||
|  |     $config_user_names = array_merge($config_user_names, | ||||||
|  |       handleSingleUserPHID($config, $userPHID)); | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleAdministratorsPolicyRule($config, $rule) { | ||||||
|  |   $administrators = id(new PhabricatorPeopleQuery()) | ||||||
|  |       ->setViewer($config->viewer) | ||||||
|  |       ->withIsAdmin(true) | ||||||
|  |       ->execute(); | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($administrators as $administrator) { | ||||||
|  |     $config_user_names = array_merge($config_user_names, | ||||||
|  |       handleSingleUserPHID($config, $administrator->getPHID())); | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSingleDocument($config, $document) { | ||||||
|  |   if ($document->getSignatureType() != | ||||||
|  |       LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |     return array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($document->getSignatures() as $signature) { | ||||||
|  |     if ($signature->getSignatureType() != | ||||||
|  |         LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |     $config_user_names = array_merge($config_user_names, | ||||||
|  |       handleSingleUserPHID($config, $signature->getSignerPHID())); | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSignaturePolicyRule($config, $rule) { | ||||||
|  |   $documents = id(new LegalpadDocumentQuery()) | ||||||
|  |     ->setViewer($config->viewer) | ||||||
|  |     ->withPHIDs($rule['value']) | ||||||
|  |     ->needSignatures(true) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   foreach ($documents as $document) { | ||||||
|  |     $config_user_names = array_merge($config_user_names, | ||||||
|  |       handleLegalpadSingleDocument($config, $document)); | ||||||
|  |   } | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleCustomPolicy($config, $policy) { | ||||||
|  |   $config_user_names = array(); | ||||||
|  |   $rules = $policy->getRules(); | ||||||
|  |   foreach ($rules as $rule) { | ||||||
|  |     // Everyone is denied by default anyway | ||||||
|  |     if ($rule['action'] != 'allow') { | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $policy_config_user_names = array(); | ||||||
|  |     $rule_type = $rule['rule']; | ||||||
|  |     if ($rule_type == 'PhabricatorPolicyRuleUsers') { | ||||||
|  |       $policy_config_user_names = | ||||||
|  |           handleUsersPolicyRule($config, $rule); | ||||||
|  |     } else if ($rule_type == 'PhabricatorProjectsPolicyRule') { | ||||||
|  |       $policy_config_user_names = | ||||||
|  |           handleProjectsPolicyRule($config, $rule); | ||||||
|  |     } else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') { | ||||||
|  |       $policy_config_user_names = | ||||||
|  |           handleProjectsAllPolicyRule($config, $rule); | ||||||
|  |     } else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') { | ||||||
|  |       $policy_config_user_names = | ||||||
|  |           handleAdministratorsPolicyRule($config, $rule); | ||||||
|  |     } else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') { | ||||||
|  |       $policy_config_user_names = | ||||||
|  |           handleLegalpadSignaturePolicyRule($config, $rule); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $config_user_names = array_merge( | ||||||
|  |         $config_user_names, $policy_config_user_names); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return $config_user_names; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Parse repository and put it's members to the config file | ||||||
|  | function handleSingleRepository($config, $repository) { | ||||||
|  |   $policies = PhabricatorPolicyQuery::loadPolicies( | ||||||
|  |     $config->viewer, | ||||||
|  |     $repository); | ||||||
|  |  | ||||||
|  |   $pushable = $policies[DiffusionPushCapability::CAPABILITY]; | ||||||
|  |   $type = $pushable->getType(); | ||||||
|  |  | ||||||
|  |   $config_user_names = array(); | ||||||
|  |  | ||||||
|  |   if ($type == PhabricatorPolicyType::TYPE_PROJECT) { | ||||||
|  |     $project = id(new PhabricatorProjectQuery()) | ||||||
|  |       ->setViewer($config->viewer) | ||||||
|  |       ->needMembers(true) | ||||||
|  |       ->withPHIDs(array($pushable->getPHID())) | ||||||
|  |       ->executeOne(); | ||||||
|  |  | ||||||
|  |     $memberPHIDs = $project->getMemberPHIDs(); | ||||||
|  |     foreach ($memberPHIDs as $memberPHID) { | ||||||
|  |       $config_user_names = array_merge($config_user_names, | ||||||
|  |           handleSingleUserPHID($config, $memberPHID)); | ||||||
|  |     } | ||||||
|  |   } else if ($type == PhabricatorPolicyType::TYPE_USER) { | ||||||
|  |     $config_user_names = handleSingleUserPHID($config, $pushable->getPHID()); | ||||||
|  |   } else if ($type == PhabricatorPolicyType::TYPE_CUSTOM) { | ||||||
|  |     $config_user_names = handleCustomPolicy($config, $pushable); | ||||||
|  |   } else { | ||||||
|  |     /* pass */ | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $config->setRepositoryUsers($repository, $config_user_names); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function rebuildConfiguration($gitolite_root) { | ||||||
|  |   $config = new Configuration($gitolite_root); | ||||||
|  |  | ||||||
|  |   // Fill in new configuration and keys | ||||||
|  |   $used_keys = array(); | ||||||
|  |   $repositories = id(new PhabricatorRepositoryQuery()) | ||||||
|  |     ->setViewer($config->viewer) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   foreach ($repositories as $repository_id => $repository) { | ||||||
|  |     $type = $repository->getVersionControlSystem(); | ||||||
|  |     if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) { | ||||||
|  |       handleSingleRepository($config, $repository); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $config->writeNewConfiguration(); | ||||||
|  |  | ||||||
|  |   $config->finalize(); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //////////////////////////////////////////////////////////////////////////////// | ||||||
|  | // Repository manipulation functionality. | ||||||
|  |  | ||||||
|  | function getGitCommand($repository) { | ||||||
|  |   $git_dir = realpath("$repository/.git"); | ||||||
|  |   $git = "git --git-dir='$git_dir'"; | ||||||
|  |   $git .= ' --work-tree='.realpath($repository); | ||||||
|  |   return $git; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function runGitCommand($repository, $arguments, | ||||||
|  |                        &$output=null, &$return_var=null) { | ||||||
|  |   $git = getGitCommand($repository); | ||||||
|  |   $git .= " $arguments"; | ||||||
|  |   exec($git, $output, $return_var); | ||||||
|  |   return $return_var == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function runGitSshCommand($repository, $key, $arguments, | ||||||
|  |                           &$output=null, &$return_var=null) { | ||||||
|  |   $abs_key = realpath($key); | ||||||
|  |   $git = "GIT_SSH_COMMAND=\"ssh -i $key -o IdentitiesOnly=yes\" "; | ||||||
|  |   $git .= getGitCommand($repository); | ||||||
|  |   $git .= " $arguments"; | ||||||
|  |   exec($git, $output, $return_var); | ||||||
|  |   return $return_var == 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function repositoryPull($repository, $key) { | ||||||
|  |   return runGitSshCommand($repository, $key, 'pull --rebase'); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function repositoryCommitAll($repository, $author, $message) { | ||||||
|  |   if (!runGitCommand( | ||||||
|  |     $repository, 'ls-files --other --exclude-standard', $untracked_files)) { | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |   if (count($untracked_files)) { | ||||||
|  |     $flat_files = join(' ', $untracked_files); | ||||||
|  |     if (!runGitCommand($repository, "add $flat_files")) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   runGitCommand($repository, "update-index -q --refresh", $output); | ||||||
|  |   runGitCommand($repository, "diff-index --name-only HEAD --", $output); | ||||||
|  |   if (count($output)) { | ||||||
|  |     return runGitCommand( | ||||||
|  |       $repository, "commit --author='$author' -a -m '$message'", $output); | ||||||
|  |   } | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (count($argv) != 3) { | ||||||
|  |   print("Usage: {$argv[0]} /path/to/gitolite-admin /path/to/id_rsa.pub\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | $gitolite_root = $argv[1]; | ||||||
|  | $key = $argv[2]; | ||||||
|  |  | ||||||
|  | if (!repositoryPull($gitolite_root, $key)) { | ||||||
|  |   print("Failed to pull changes from server.\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!rebuildConfiguration($gitolite_root)) { | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (!repositoryCommitAll( | ||||||
|  |   $gitolite_root, 'Rebuild Gitadmin <null@git.blender.org>', | ||||||
|  |   'Update to correspond changes in Phabricator')) { | ||||||
|  |   print("Failed to commit changes.\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | runGitSshCommand($gitolite_root, $key, 'push origin master'); | ||||||
|  | ?> | ||||||
| @@ -8,10 +8,14 @@ function init_phabricator_script(array $options) { | |||||||
|   ini_set( |   ini_set( | ||||||
|     'include_path', |     'include_path', | ||||||
|     $include_path.PATH_SEPARATOR.dirname(__FILE__).'/../../../'); |     $include_path.PATH_SEPARATOR.dirname(__FILE__).'/../../../'); | ||||||
|   @include_once 'libphutil/scripts/__init_script__.php'; |  | ||||||
|   if (!@constant('__LIBPHUTIL__')) { |   $ok = @include_once 'arcanist/support/init/init-script.php'; | ||||||
|     echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ". |   if (!$ok) { | ||||||
|       "include the parent directory of libphutil/.\n"; |     echo | ||||||
|  |       'FATAL ERROR: Unable to load the "Arcanist" library. '. | ||||||
|  |       'Put "arcanist/" next to "phabricator/" on disk.'; | ||||||
|  |     echo "\n"; | ||||||
|  |  | ||||||
|     exit(1); |     exit(1); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ failed() { | |||||||
| } | } | ||||||
|  |  | ||||||
| ISSUE=`cat /etc/issue` | ISSUE=`cat /etc/issue` | ||||||
| if [[ $ISSUE != Ubuntu* ]] | if [[ ($ISSUE != Ubuntu*) && ($ISSUE != Debian*) ]]; | ||||||
| then | then | ||||||
|   echo "This script is intended for use on Ubuntu, but this system appears"; |   echo "This script is intended for use on Ubuntu, but this system appears"; | ||||||
|   echo "to be something else. Your results may vary."; |   echo "to be something else. Your results may vary."; | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								scripts/svnauth/archived_repos.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,61 @@ | |||||||
|  | <?php | ||||||
|  |   $ARCHIVED_REPOS = array( | ||||||
|  |     'abstractmesh', | ||||||
|  |     'beast', | ||||||
|  | #    'bf-blender', | ||||||
|  |     'bf-docboard-es', | ||||||
|  |     'bf-extensions', | ||||||
|  |     'bf-funboard', | ||||||
|  |     'bf-scripts', | ||||||
|  | #    'bf-translations', | ||||||
|  |     'bfct', | ||||||
|  |     'bforge', | ||||||
|  |     'blend-doc', | ||||||
|  |     'blend2cs', | ||||||
|  |     'blendedmidi', | ||||||
|  |     'blendercad', | ||||||
|  |     'blendxml', | ||||||
|  |     'bzoo', | ||||||
|  |     'docboard', | ||||||
|  |     'drqueue', | ||||||
|  |     'ghost', | ||||||
|  |     'girona', | ||||||
|  |     'guiman', | ||||||
|  |     'lsystem', | ||||||
|  |     'magic', | ||||||
|  |     'makeh', | ||||||
|  |     'mechanicblender', | ||||||
|  |     'neverblender', | ||||||
|  |     'news', | ||||||
|  |     'night', | ||||||
|  |     'nitrox', | ||||||
|  |     'osgexport', | ||||||
|  |     'peerrating', | ||||||
|  |     'piovra', | ||||||
|  |     'pyverse', | ||||||
|  |     'qdune', | ||||||
|  |     'scolblender', | ||||||
|  |     'skined', | ||||||
|  |     'smdio', | ||||||
|  |     'soapyblender', | ||||||
|  |     'soc-2005', | ||||||
|  |     'soc-2006', | ||||||
|  |     'soc-2007', | ||||||
|  |     'soc-2008', | ||||||
|  |     'sourceforge', | ||||||
|  |     'spe', | ||||||
|  |     'stats', | ||||||
|  |     'ter2blend', | ||||||
|  |     'torqueexporter', | ||||||
|  |     'tuhopuu', | ||||||
|  |     'tzuray', | ||||||
|  |     'vectex', | ||||||
|  |     'vectorrender', | ||||||
|  |     'verse', | ||||||
|  |     'vrmlimportexp', | ||||||
|  |     'warblender', | ||||||
|  |     'wpyre', | ||||||
|  |     'yafray', | ||||||
|  |     'yofrankie' | ||||||
|  |   ); | ||||||
|  | ?> | ||||||
							
								
								
									
										292
									
								
								scripts/svnauth/rebuild_svnauth.php
									
									
									
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,292 @@ | |||||||
|  | #!/usr/local/bin/php | ||||||
|  | <?php | ||||||
|  |  | ||||||
|  | $root = dirname(dirname(dirname(__FILE__))); | ||||||
|  | require_once $root.'/scripts/__init_script__.php'; | ||||||
|  |  | ||||||
|  | function getSVNRepositoryName($repository) { | ||||||
|  |   $uri = $repository->getRemoteURI(); | ||||||
|  |   return preg_replace( | ||||||
|  |     '/https?\:\/\/.*?\/svnroot\/([^\/]+)\/?.*/', '$1', $uri); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Get user's heys and put them to the configuration | ||||||
|  | function handleSingleUserPHID( | ||||||
|  |   $viewer, $userPHID, $repository, &$namemap, &$access) { | ||||||
|  |   $user = id(new PhabricatorPeopleQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withPHIDs(array($userPHID)) | ||||||
|  |     ->executeOne(); | ||||||
|  |   if (!$user) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ($user->getIsDisabled()) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $user_name = $user->getUserName(); | ||||||
|  |   if (!array_key_exists($user_name, $namemap)) { | ||||||
|  |     $namemap[$user_name] = array('email' => $user->loadPrimaryEmailAddress(), | ||||||
|  |                                  'name' => $user->getRealName()); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $repository_name = getSVNRepositoryName($repository); | ||||||
|  |  | ||||||
|  |   $repository_rootpath = $repository_name . ':/'; | ||||||
|  |   if (!array_key_exists($repository_rootpath, $access)) { | ||||||
|  |     $access[$repository_rootpath]['RW'] = array(); | ||||||
|  |     $access[$repository_rootpath]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |   $access[$repository_rootpath]['RO'][] = $user_name; | ||||||
|  |  | ||||||
|  |   // Store write access settings to current subath | ||||||
|  |   $subpath = $repository->getDetail('svn-subpath'); | ||||||
|  |   $subpath = rtrim($subpath, '/'); | ||||||
|  |   $repository_pathname = "$repository_name:/$subpath"; | ||||||
|  |   if (!array_key_exists($repository_pathname, $access)) { | ||||||
|  |     $access[$repository_pathname]['RW'] = array(); | ||||||
|  |     $access[$repository_pathname]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |   $access[$repository_pathname]['RW'][] = $user_name; | ||||||
|  |  | ||||||
|  |   // Write access to the tags | ||||||
|  |   $tags_pathname = "$repository_name:/tags"; | ||||||
|  |   if (!array_key_exists($tags_pathname, $access)) { | ||||||
|  |     $access[$tags_pathname]['RW'] = array(); | ||||||
|  |     $access[$tags_pathname]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |   $access[$tags_pathname]['RW'][] = $user_name; | ||||||
|  |  | ||||||
|  |   // Write access to the branches. | ||||||
|  |   $branches_pathname = "$repository_name:/branches"; | ||||||
|  |   if (!array_key_exists($branches_pathname, $access)) { | ||||||
|  |     $access[$branches_pathname]['RW'] = array(); | ||||||
|  |     $access[$branches_pathname]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |   $access[$branches_pathname]['RW'][] = $user_name; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function getProjectMembersPHIDs($viewer, $project_phid) { | ||||||
|  |   $project = id(new PhabricatorProjectQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->needMembers(true) | ||||||
|  |     ->withPHIDs(array($project_phid)) | ||||||
|  |     ->executeOne(); | ||||||
|  |  | ||||||
|  |   return $project->getMemberPHIDs(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectPHID( | ||||||
|  |   $viewer, $project_phid, $repository, &$namemap, &$access) { | ||||||
|  |   $memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid); | ||||||
|  |   foreach ($memberPHIDs as $memberPHID) { | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $memberPHID, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleUsersPolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   foreach ($rule['value'] as $user_phid) { | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $user_phid, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsPolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   foreach ($rule['value'] as $project_phid) { | ||||||
|  |     handleProjectPHID( | ||||||
|  |       $viewer, $project_phid, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleProjectsAllPolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   $is_first_project = true; | ||||||
|  |   $allowed_members_phids = array(); | ||||||
|  |   foreach ($rule['value'] as $project_phid) { | ||||||
|  |     $memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid); | ||||||
|  |     if ($is_first_project) { | ||||||
|  |       $allowed_members_phids = $memberPHIDs; | ||||||
|  |       $is_first_project = false; | ||||||
|  |     } else { | ||||||
|  |       $allowed_members_phids = array_intersect( | ||||||
|  |         $allowed_members_phids, $memberPHIDs); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   foreach ($allowed_members_phids as $user_phid) { | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $user_phid, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleAdministratorsPolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   $administrators = id(new PhabricatorPeopleQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withIsAdmin(true) | ||||||
|  |     ->execute(); | ||||||
|  |   foreach ($administrators as $administrator) { | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $administrator->getPHID(), $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSingleDocument( | ||||||
|  |   $viewer, $document, $repository, &$namemap, &$access) { | ||||||
|  |   if ($document->getSignatureType() != | ||||||
|  |       LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   foreach ($document->getSignatures() as $signature) { | ||||||
|  |     if ($signature->getSignatureType() != | ||||||
|  |         LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) { | ||||||
|  |       continue; | ||||||
|  |     } | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $signature->getSignerPHID(), $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleLegalpadSignaturePolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   $documents = id(new LegalpadDocumentQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->withPHIDs($rule['value']) | ||||||
|  |     ->needSignatures(true) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   foreach ($documents as $document) { | ||||||
|  |     handleLegalpadSingleDocument( | ||||||
|  |       $viewer, $document, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleCustomPolicyRule( | ||||||
|  |   $viewer, $rule, $repository, &$namemap, &$access) { | ||||||
|  |   if ($rule['action'] != PhabricatorPolicy::ACTION_ALLOW) { | ||||||
|  |     // By default the script decides to DENY unless explicitly allowed. | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   $rule_type = $rule['rule']; | ||||||
|  |   if ($rule_type == 'PhabricatorUsersPolicyRule') { | ||||||
|  |     handleUsersPolicyRule( | ||||||
|  |       $viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } else if ($rule_type == 'PhabricatorProjectsPolicyRule') { | ||||||
|  |     handleProjectsPolicyRule( | ||||||
|  |       $viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') { | ||||||
|  |     handleProjectsAllPolicyRule( | ||||||
|  |       $viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') { | ||||||
|  |     handleAdministratorsPolicyRule( | ||||||
|  |       $viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') { | ||||||
|  |     handleLegalpadSignaturePolicyRule( | ||||||
|  |       $viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function handleCustomPolicy( | ||||||
|  |   $viewer, $policy, $repository, &$namemap, &$access) { | ||||||
|  |   foreach ($policy->getRules() as $rule) { | ||||||
|  |     handleCustomPolicyRule($viewer, $rule, $repository, $namemap, $access); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Parse repository and put it's members to the config file | ||||||
|  | function handleSingleRepository( | ||||||
|  |   $viewer, $repository, &$namemap, &$access) { | ||||||
|  |   $policies = PhabricatorPolicyQuery::loadPolicies( | ||||||
|  |     $viewer, | ||||||
|  |     $repository); | ||||||
|  |  | ||||||
|  |   $pushable = $policies[DiffusionPushCapability::CAPABILITY]; | ||||||
|  |   $type = phid_get_type($pushable->getPHID()); | ||||||
|  |  | ||||||
|  |   // Make sure repository is always available for read-only access | ||||||
|  |   $repository_rootpath = getSVNRepositoryName($repository) . ':/'; | ||||||
|  |   if (!array_key_exists($repository_rootpath, $access)) { | ||||||
|  |     $access[$repository_rootpath]['RW'] = array(); | ||||||
|  |     $access[$repository_rootpath]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ($type == PhabricatorProjectProjectPHIDType::TYPECONST) { | ||||||
|  |     handleProjectPHID( | ||||||
|  |       $viewer, $pushable->getPHID(), $repository, $namemap, $access); | ||||||
|  |   } else if ($type == PhabricatorPolicyType::TYPE_USER) { | ||||||
|  |     handleSingleUserPHID( | ||||||
|  |       $viewer, $pushable->getPHID(), $repository, $namemap, $access); | ||||||
|  |   } else if ($type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) { | ||||||
|  |     handleCustomPolicy( | ||||||
|  |       $viewer, $pushable, $repository, $namemap, $access); | ||||||
|  |     /* pass */ | ||||||
|  |   } else { | ||||||
|  |     /* pass */ | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | function rebuildConfiguration($what) { | ||||||
|  |   $viewer = id(new PhabricatorUser()) | ||||||
|  |     ->loadOneWhere('username = %s', 'sergey'); | ||||||
|  |  | ||||||
|  |   $repositories = id(new PhabricatorRepositoryQuery()) | ||||||
|  |     ->setViewer($viewer) | ||||||
|  |     ->execute(); | ||||||
|  |  | ||||||
|  |   $namemap = array(); | ||||||
|  |   $access = array(); | ||||||
|  |  | ||||||
|  |   require_once 'archived_repos.php'; | ||||||
|  |   foreach ($ARCHIVED_REPOS as $repository) { | ||||||
|  |     $repository_pathname = "$repository:/"; | ||||||
|  |     $access[$repository_pathname]['RW'] = array(); | ||||||
|  |     $access[$repository_pathname]['RO'] = array(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   foreach ($repositories as $repository_id => $repository) { | ||||||
|  |     $type = $repository->getVersionControlSystem(); | ||||||
|  |     if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) { | ||||||
|  |       handleSingleRepository( | ||||||
|  |         $viewer, $repository, $namemap, $access); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if ($what == 'ACCESS') { | ||||||
|  |     foreach ($access as $repository => $users) { | ||||||
|  |       print("[$repository]\n"); | ||||||
|  |       $rw_users = array(); | ||||||
|  |       foreach ($users['RW'] as $user) { | ||||||
|  |         print("$user = rw\n"); | ||||||
|  |         $rw_users[$user] = true; | ||||||
|  |       } | ||||||
|  |       foreach ($users['RO'] as $user) { | ||||||
|  |         if (!array_key_exists($user, $rw_users)) { | ||||||
|  |           print("$user = r\n"); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |       print("anonsvn = r\n"); | ||||||
|  |       print("* = r\n\n"); | ||||||
|  |     } | ||||||
|  |   } else if ($what == 'NAMEMAP') { | ||||||
|  |     foreach ($namemap as $user => $data) { | ||||||
|  |       print("$user\t${data['email']}\t${data['name']}\n"); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | if (count($argv) != 2 || | ||||||
|  |     ($argv[1] != 'ACCESS' && $argv[1] != 'NAMEMAP')) { | ||||||
|  |   print("Usage: {$argv[0]} ACCESS|NAMEMAP\n"); | ||||||
|  |   exit(1); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | rebuildConfiguration($argv[1]); | ||||||
|  | ?> | ||||||
| @@ -179,6 +179,7 @@ phutil_register_library_map(array( | |||||||
|     'AphrontAccessDeniedQueryException' => 'infrastructure/storage/exception/AphrontAccessDeniedQueryException.php', |     'AphrontAccessDeniedQueryException' => 'infrastructure/storage/exception/AphrontAccessDeniedQueryException.php', | ||||||
|     'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php', |     'AphrontAjaxResponse' => 'aphront/response/AphrontAjaxResponse.php', | ||||||
|     'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php', |     'AphrontApplicationConfiguration' => 'aphront/configuration/AphrontApplicationConfiguration.php', | ||||||
|  |     'AphrontAutoIDView' => 'view/AphrontAutoIDView.php', | ||||||
|     'AphrontBarView' => 'view/widget/bars/AphrontBarView.php', |     'AphrontBarView' => 'view/widget/bars/AphrontBarView.php', | ||||||
|     'AphrontBaseMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php', |     'AphrontBaseMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontBaseMySQLDatabaseConnection.php', | ||||||
|     'AphrontBoolHTTPParameterType' => 'aphront/httpparametertype/AphrontBoolHTTPParameterType.php', |     'AphrontBoolHTTPParameterType' => 'aphront/httpparametertype/AphrontBoolHTTPParameterType.php', | ||||||
| @@ -224,6 +225,8 @@ phutil_register_library_map(array( | |||||||
|     'AphrontFormView' => 'view/form/AphrontFormView.php', |     'AphrontFormView' => 'view/form/AphrontFormView.php', | ||||||
|     'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php', |     'AphrontGlyphBarView' => 'view/widget/bars/AphrontGlyphBarView.php', | ||||||
|     'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php', |     'AphrontHTMLResponse' => 'aphront/response/AphrontHTMLResponse.php', | ||||||
|  |     'AphrontHTTPHeaderParser' => 'aphront/headerparser/AphrontHTTPHeaderParser.php', | ||||||
|  |     'AphrontHTTPHeaderParserTestCase' => 'aphront/headerparser/__tests__/AphrontHTTPHeaderParserTestCase.php', | ||||||
|     'AphrontHTTPParameterType' => 'aphront/httpparametertype/AphrontHTTPParameterType.php', |     'AphrontHTTPParameterType' => 'aphront/httpparametertype/AphrontHTTPParameterType.php', | ||||||
|     'AphrontHTTPProxyResponse' => 'aphront/response/AphrontHTTPProxyResponse.php', |     'AphrontHTTPProxyResponse' => 'aphront/response/AphrontHTTPProxyResponse.php', | ||||||
|     'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php', |     'AphrontHTTPSink' => 'aphront/sink/AphrontHTTPSink.php', | ||||||
| @@ -242,6 +245,9 @@ phutil_register_library_map(array( | |||||||
|     'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php', |     'AphrontMalformedRequestException' => 'aphront/exception/AphrontMalformedRequestException.php', | ||||||
|     'AphrontMoreView' => 'view/layout/AphrontMoreView.php', |     'AphrontMoreView' => 'view/layout/AphrontMoreView.php', | ||||||
|     'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php', |     'AphrontMultiColumnView' => 'view/layout/AphrontMultiColumnView.php', | ||||||
|  |     'AphrontMultipartParser' => 'aphront/multipartparser/AphrontMultipartParser.php', | ||||||
|  |     'AphrontMultipartParserTestCase' => 'aphront/multipartparser/__tests__/AphrontMultipartParserTestCase.php', | ||||||
|  |     'AphrontMultipartPart' => 'aphront/multipartparser/AphrontMultipartPart.php', | ||||||
|     'AphrontMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php', |     'AphrontMySQLDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLDatabaseConnection.php', | ||||||
|     'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', |     'AphrontMySQLDatabaseConnectionTestCase' => 'infrastructure/storage/__tests__/AphrontMySQLDatabaseConnectionTestCase.php', | ||||||
|     'AphrontMySQLiDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php', |     'AphrontMySQLiDatabaseConnection' => 'infrastructure/storage/connection/mysql/AphrontMySQLiDatabaseConnection.php', | ||||||
| @@ -265,12 +271,15 @@ phutil_register_library_map(array( | |||||||
|     'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php', |     'AphrontReloadResponse' => 'aphront/response/AphrontReloadResponse.php', | ||||||
|     'AphrontRequest' => 'aphront/AphrontRequest.php', |     'AphrontRequest' => 'aphront/AphrontRequest.php', | ||||||
|     'AphrontRequestExceptionHandler' => 'aphront/handler/AphrontRequestExceptionHandler.php', |     'AphrontRequestExceptionHandler' => 'aphront/handler/AphrontRequestExceptionHandler.php', | ||||||
|  |     'AphrontRequestStream' => 'aphront/requeststream/AphrontRequestStream.php', | ||||||
|     'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php', |     'AphrontRequestTestCase' => 'aphront/__tests__/AphrontRequestTestCase.php', | ||||||
|     'AphrontResponse' => 'aphront/response/AphrontResponse.php', |     'AphrontResponse' => 'aphront/response/AphrontResponse.php', | ||||||
|     'AphrontResponseProducerInterface' => 'aphront/interface/AphrontResponseProducerInterface.php', |     'AphrontResponseProducerInterface' => 'aphront/interface/AphrontResponseProducerInterface.php', | ||||||
|     'AphrontRoutingMap' => 'aphront/site/AphrontRoutingMap.php', |     'AphrontRoutingMap' => 'aphront/site/AphrontRoutingMap.php', | ||||||
|  |     'AphrontRoutingMapTestCase' => 'aphront/__tests__/AphrontRoutingMapTestCase.php', | ||||||
|     'AphrontRoutingResult' => 'aphront/site/AphrontRoutingResult.php', |     'AphrontRoutingResult' => 'aphront/site/AphrontRoutingResult.php', | ||||||
|     'AphrontSchemaQueryException' => 'infrastructure/storage/exception/AphrontSchemaQueryException.php', |     'AphrontSchemaQueryException' => 'infrastructure/storage/exception/AphrontSchemaQueryException.php', | ||||||
|  |     'AphrontScopedUnguardedWriteCapability' => 'aphront/writeguard/AphrontScopedUnguardedWriteCapability.php', | ||||||
|     'AphrontSelectHTTPParameterType' => 'aphront/httpparametertype/AphrontSelectHTTPParameterType.php', |     'AphrontSelectHTTPParameterType' => 'aphront/httpparametertype/AphrontSelectHTTPParameterType.php', | ||||||
|     'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php', |     'AphrontSideNavFilterView' => 'view/layout/AphrontSideNavFilterView.php', | ||||||
|     'AphrontSite' => 'aphront/site/AphrontSite.php', |     'AphrontSite' => 'aphront/site/AphrontSite.php', | ||||||
| @@ -286,6 +295,7 @@ phutil_register_library_map(array( | |||||||
|     'AphrontUserListHTTPParameterType' => 'aphront/httpparametertype/AphrontUserListHTTPParameterType.php', |     'AphrontUserListHTTPParameterType' => 'aphront/httpparametertype/AphrontUserListHTTPParameterType.php', | ||||||
|     'AphrontView' => 'view/AphrontView.php', |     'AphrontView' => 'view/AphrontView.php', | ||||||
|     'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', |     'AphrontWebpageResponse' => 'aphront/response/AphrontWebpageResponse.php', | ||||||
|  |     'AphrontWriteGuard' => 'aphront/writeguard/AphrontWriteGuard.php', | ||||||
|     'ArcanistConduitAPIMethod' => 'applications/arcanist/conduit/ArcanistConduitAPIMethod.php', |     'ArcanistConduitAPIMethod' => 'applications/arcanist/conduit/ArcanistConduitAPIMethod.php', | ||||||
|     'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php', |     'AuditConduitAPIMethod' => 'applications/audit/conduit/AuditConduitAPIMethod.php', | ||||||
|     'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php', |     'AuditQueryConduitAPIMethod' => 'applications/audit/conduit/AuditQueryConduitAPIMethod.php', | ||||||
| @@ -456,7 +466,6 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialChangeset' => 'applications/differential/storage/DifferentialChangeset.php', |     'DifferentialChangeset' => 'applications/differential/storage/DifferentialChangeset.php', | ||||||
|     'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php', |     'DifferentialChangesetDetailView' => 'applications/differential/view/DifferentialChangesetDetailView.php', | ||||||
|     'DifferentialChangesetEngine' => 'applications/differential/engine/DifferentialChangesetEngine.php', |     'DifferentialChangesetEngine' => 'applications/differential/engine/DifferentialChangesetEngine.php', | ||||||
|     'DifferentialChangesetFileTreeSideNavBuilder' => 'applications/differential/view/DifferentialChangesetFileTreeSideNavBuilder.php', |  | ||||||
|     'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', |     'DifferentialChangesetHTMLRenderer' => 'applications/differential/render/DifferentialChangesetHTMLRenderer.php', | ||||||
|     'DifferentialChangesetListController' => 'applications/differential/controller/DifferentialChangesetListController.php', |     'DifferentialChangesetListController' => 'applications/differential/controller/DifferentialChangesetListController.php', | ||||||
|     'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php', |     'DifferentialChangesetListView' => 'applications/differential/view/DifferentialChangesetListView.php', | ||||||
| @@ -529,6 +538,7 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', |     'DifferentialExactUserFunctionDatasource' => 'applications/differential/typeahead/DifferentialExactUserFunctionDatasource.php', | ||||||
|     'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', |     'DifferentialFieldParseException' => 'applications/differential/exception/DifferentialFieldParseException.php', | ||||||
|     'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', |     'DifferentialFieldValidationException' => 'applications/differential/exception/DifferentialFieldValidationException.php', | ||||||
|  |     'DifferentialFileTreeEngine' => 'applications/differential/engine/DifferentialFileTreeEngine.php', | ||||||
|     'DifferentialGetAllDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetAllDiffsConduitAPIMethod.php', |     'DifferentialGetAllDiffsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetAllDiffsConduitAPIMethod.php', | ||||||
|     'DifferentialGetCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php', |     'DifferentialGetCommitMessageConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitMessageConduitAPIMethod.php', | ||||||
|     'DifferentialGetCommitPathsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitPathsConduitAPIMethod.php', |     'DifferentialGetCommitPathsConduitAPIMethod' => 'applications/differential/conduit/DifferentialGetCommitPathsConduitAPIMethod.php', | ||||||
| @@ -551,7 +561,6 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialInlineComment' => 'applications/differential/storage/DifferentialInlineComment.php', |     'DifferentialInlineComment' => 'applications/differential/storage/DifferentialInlineComment.php', | ||||||
|     'DifferentialInlineCommentEditController' => 'applications/differential/controller/DifferentialInlineCommentEditController.php', |     'DifferentialInlineCommentEditController' => 'applications/differential/controller/DifferentialInlineCommentEditController.php', | ||||||
|     'DifferentialInlineCommentMailView' => 'applications/differential/mail/DifferentialInlineCommentMailView.php', |     'DifferentialInlineCommentMailView' => 'applications/differential/mail/DifferentialInlineCommentMailView.php', | ||||||
|     'DifferentialInlineCommentQuery' => 'applications/differential/query/DifferentialInlineCommentQuery.php', |  | ||||||
|     'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', |     'DifferentialJIRAIssuesCommitMessageField' => 'applications/differential/field/DifferentialJIRAIssuesCommitMessageField.php', | ||||||
|     'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', |     'DifferentialJIRAIssuesField' => 'applications/differential/customfield/DifferentialJIRAIssuesField.php', | ||||||
|     'DifferentialLegacyQuery' => 'applications/differential/constants/DifferentialLegacyQuery.php', |     'DifferentialLegacyQuery' => 'applications/differential/constants/DifferentialLegacyQuery.php', | ||||||
| @@ -704,6 +713,9 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php', |     'DifferentialUnitStatus' => 'applications/differential/constants/DifferentialUnitStatus.php', | ||||||
|     'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php', |     'DifferentialUnitTestResult' => 'applications/differential/constants/DifferentialUnitTestResult.php', | ||||||
|     'DifferentialUpdateRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateRevisionConduitAPIMethod.php', |     'DifferentialUpdateRevisionConduitAPIMethod' => 'applications/differential/conduit/DifferentialUpdateRevisionConduitAPIMethod.php', | ||||||
|  |     'DifferentialViewState' => 'applications/differential/storage/DifferentialViewState.php', | ||||||
|  |     'DifferentialViewStateGarbageCollector' => 'applications/differential/garbagecollector/DifferentialViewStateGarbageCollector.php', | ||||||
|  |     'DifferentialViewStateQuery' => 'applications/differential/query/DifferentialViewStateQuery.php', | ||||||
|     'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php', |     'DiffusionAuditorDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorDatasource.php', | ||||||
|     'DiffusionAuditorFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php', |     'DiffusionAuditorFunctionDatasource' => 'applications/diffusion/typeahead/DiffusionAuditorFunctionDatasource.php', | ||||||
|     'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php', |     'DiffusionAuditorsAddAuditorsHeraldAction' => 'applications/diffusion/herald/DiffusionAuditorsAddAuditorsHeraldAction.php', | ||||||
| @@ -864,7 +876,6 @@ phutil_register_library_map(array( | |||||||
|     'DiffusionIdentityUnassignedDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php', |     'DiffusionIdentityUnassignedDatasource' => 'applications/diffusion/typeahead/DiffusionIdentityUnassignedDatasource.php', | ||||||
|     'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php', |     'DiffusionIdentityViewController' => 'applications/diffusion/controller/DiffusionIdentityViewController.php', | ||||||
|     'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', |     'DiffusionInlineCommentController' => 'applications/diffusion/controller/DiffusionInlineCommentController.php', | ||||||
|     'DiffusionInlineCommentPreviewController' => 'applications/diffusion/controller/DiffusionInlineCommentPreviewController.php', |  | ||||||
|     'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.php', |     'DiffusionInternalAncestorsConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalAncestorsConduitAPIMethod.php', | ||||||
|     'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalGitRawDiffQueryConduitAPIMethod.php', |     'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'applications/diffusion/conduit/DiffusionInternalGitRawDiffQueryConduitAPIMethod.php', | ||||||
|     'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php', |     'DiffusionLastModifiedController' => 'applications/diffusion/controller/DiffusionLastModifiedController.php', | ||||||
| @@ -1279,6 +1290,8 @@ phutil_register_library_map(array( | |||||||
|     'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php', |     'FeedPushWorker' => 'applications/feed/worker/FeedPushWorker.php', | ||||||
|     'FeedQueryConduitAPIMethod' => 'applications/feed/conduit/FeedQueryConduitAPIMethod.php', |     'FeedQueryConduitAPIMethod' => 'applications/feed/conduit/FeedQueryConduitAPIMethod.php', | ||||||
|     'FeedStoryNotificationGarbageCollector' => 'applications/notification/garbagecollector/FeedStoryNotificationGarbageCollector.php', |     'FeedStoryNotificationGarbageCollector' => 'applications/notification/garbagecollector/FeedStoryNotificationGarbageCollector.php', | ||||||
|  |     'FerretConfigurableSearchFunction' => 'applications/search/ferret/function/FerretConfigurableSearchFunction.php', | ||||||
|  |     'FerretSearchFunction' => 'applications/search/ferret/function/FerretSearchFunction.php', | ||||||
|     'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php', |     'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php', | ||||||
|     'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php', |     'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php', | ||||||
|     'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php', |     'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php', | ||||||
| @@ -1760,6 +1773,7 @@ phutil_register_library_map(array( | |||||||
|     'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', |     'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php', | ||||||
|     'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php', |     'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php', | ||||||
|     'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php', |     'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php', | ||||||
|  |     'ManiphestSearchController' => 'applications/maniphest/controller/ManiphestSearchController.php', | ||||||
|     'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', |     'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php', | ||||||
|     'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php', |     'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php', | ||||||
|     'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php', |     'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php', | ||||||
| @@ -1991,6 +2005,8 @@ phutil_register_library_map(array( | |||||||
|     'PHUICrumbView' => 'view/phui/PHUICrumbView.php', |     'PHUICrumbView' => 'view/phui/PHUICrumbView.php', | ||||||
|     'PHUICrumbsView' => 'view/phui/PHUICrumbsView.php', |     'PHUICrumbsView' => 'view/phui/PHUICrumbsView.php', | ||||||
|     'PHUICurtainExtension' => 'view/extension/PHUICurtainExtension.php', |     'PHUICurtainExtension' => 'view/extension/PHUICurtainExtension.php', | ||||||
|  |     'PHUICurtainObjectRefListView' => 'view/phui/PHUICurtainObjectRefListView.php', | ||||||
|  |     'PHUICurtainObjectRefView' => 'view/phui/PHUICurtainObjectRefView.php', | ||||||
|     'PHUICurtainPanelView' => 'view/layout/PHUICurtainPanelView.php', |     'PHUICurtainPanelView' => 'view/layout/PHUICurtainPanelView.php', | ||||||
|     'PHUICurtainView' => 'view/layout/PHUICurtainView.php', |     'PHUICurtainView' => 'view/layout/PHUICurtainView.php', | ||||||
|     'PHUIDiffGraphView' => 'infrastructure/diff/view/PHUIDiffGraphView.php', |     'PHUIDiffGraphView' => 'infrastructure/diff/view/PHUIDiffGraphView.php', | ||||||
| @@ -2020,6 +2036,14 @@ phutil_register_library_map(array( | |||||||
|     'PHUIFormLayoutView' => 'view/form/PHUIFormLayoutView.php', |     'PHUIFormLayoutView' => 'view/form/PHUIFormLayoutView.php', | ||||||
|     'PHUIFormNumberControl' => 'view/form/control/PHUIFormNumberControl.php', |     'PHUIFormNumberControl' => 'view/form/control/PHUIFormNumberControl.php', | ||||||
|     'PHUIFormTimerControl' => 'view/form/control/PHUIFormTimerControl.php', |     'PHUIFormTimerControl' => 'view/form/control/PHUIFormTimerControl.php', | ||||||
|  |     'PHUIFormationColumnDynamicView' => 'view/formation/PHUIFormationColumnDynamicView.php', | ||||||
|  |     'PHUIFormationColumnItem' => 'view/formation/PHUIFormationColumnItem.php', | ||||||
|  |     'PHUIFormationColumnView' => 'view/formation/PHUIFormationColumnView.php', | ||||||
|  |     'PHUIFormationContentView' => 'view/formation/PHUIFormationContentView.php', | ||||||
|  |     'PHUIFormationExpanderView' => 'view/formation/PHUIFormationExpanderView.php', | ||||||
|  |     'PHUIFormationFlankView' => 'view/formation/PHUIFormationFlankView.php', | ||||||
|  |     'PHUIFormationResizerView' => 'view/formation/PHUIFormationResizerView.php', | ||||||
|  |     'PHUIFormationView' => 'view/formation/PHUIFormationView.php', | ||||||
|     'PHUIHandleListView' => 'applications/phid/view/PHUIHandleListView.php', |     'PHUIHandleListView' => 'applications/phid/view/PHUIHandleListView.php', | ||||||
|     'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', |     'PHUIHandleTagListView' => 'applications/phid/view/PHUIHandleTagListView.php', | ||||||
|     'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', |     'PHUIHandleView' => 'applications/phid/view/PHUIHandleView.php', | ||||||
| @@ -2037,8 +2061,10 @@ phutil_register_library_map(array( | |||||||
|     'PHUIInfoView' => 'view/phui/PHUIInfoView.php', |     'PHUIInfoView' => 'view/phui/PHUIInfoView.php', | ||||||
|     'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php', |     'PHUIInvisibleCharacterTestCase' => 'view/phui/__tests__/PHUIInvisibleCharacterTestCase.php', | ||||||
|     'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php', |     'PHUIInvisibleCharacterView' => 'view/phui/PHUIInvisibleCharacterView.php', | ||||||
|  |     'PHUILauncherView' => 'view/phui/PHUILauncherView.php', | ||||||
|     'PHUILeftRightExample' => 'applications/uiexample/examples/PHUILeftRightExample.php', |     'PHUILeftRightExample' => 'applications/uiexample/examples/PHUILeftRightExample.php', | ||||||
|     'PHUILeftRightView' => 'view/phui/PHUILeftRightView.php', |     'PHUILeftRightView' => 'view/phui/PHUILeftRightView.php', | ||||||
|  |     'PHUILinkView' => 'view/phui/PHUILinkView.php', | ||||||
|     'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', |     'PHUIListExample' => 'applications/uiexample/examples/PHUIListExample.php', | ||||||
|     'PHUIListItemView' => 'view/phui/PHUIListItemView.php', |     'PHUIListItemView' => 'view/phui/PHUIListItemView.php', | ||||||
|     'PHUIListView' => 'view/phui/PHUIListView.php', |     'PHUIListView' => 'view/phui/PHUIListView.php', | ||||||
| @@ -2140,6 +2166,7 @@ phutil_register_library_map(array( | |||||||
|     'PasteSearchConduitAPIMethod' => 'applications/paste/conduit/PasteSearchConduitAPIMethod.php', |     'PasteSearchConduitAPIMethod' => 'applications/paste/conduit/PasteSearchConduitAPIMethod.php', | ||||||
|     'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php', |     'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php', | ||||||
|     'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php', |     'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php', | ||||||
|  |     'PeopleDisableSpamUsersCapability' => 'applications/people/capability/PeopleDisableSpamUsersCapability.php', | ||||||
|     'PeopleDisableUsersCapability' => 'applications/people/capability/PeopleDisableUsersCapability.php', |     'PeopleDisableUsersCapability' => 'applications/people/capability/PeopleDisableUsersCapability.php', | ||||||
|     'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php', |     'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php', | ||||||
|     'PeopleMainMenuBarExtension' => 'applications/people/engineextension/PeopleMainMenuBarExtension.php', |     'PeopleMainMenuBarExtension' => 'applications/people/engineextension/PeopleMainMenuBarExtension.php', | ||||||
| @@ -2201,6 +2228,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorApplicationSearchResultView' => 'applications/search/view/PhabricatorApplicationSearchResultView.php', |     'PhabricatorApplicationSearchResultView' => 'applications/search/view/PhabricatorApplicationSearchResultView.php', | ||||||
|     'PhabricatorApplicationTestCase' => 'applications/base/__tests__/PhabricatorApplicationTestCase.php', |     'PhabricatorApplicationTestCase' => 'applications/base/__tests__/PhabricatorApplicationTestCase.php', | ||||||
|     'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php', |     'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php', | ||||||
|  |     'PhabricatorApplicationTransactionCannedResponsesController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCannedResponsesController.php', | ||||||
|     'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php', |     'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php', | ||||||
|     'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php', |     'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php', | ||||||
|     'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', |     'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php', | ||||||
| @@ -2720,6 +2748,8 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorChangePasswordUserLogType' => 'applications/people/userlog/PhabricatorChangePasswordUserLogType.php', |     'PhabricatorChangePasswordUserLogType' => 'applications/people/userlog/PhabricatorChangePasswordUserLogType.php', | ||||||
|     'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php', |     'PhabricatorChangesetCachePurger' => 'applications/cache/purger/PhabricatorChangesetCachePurger.php', | ||||||
|     'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', |     'PhabricatorChangesetResponse' => 'infrastructure/diff/PhabricatorChangesetResponse.php', | ||||||
|  |     'PhabricatorChangesetViewState' => 'infrastructure/diff/viewstate/PhabricatorChangesetViewState.php', | ||||||
|  |     'PhabricatorChangesetViewStateEngine' => 'infrastructure/diff/viewstate/PhabricatorChangesetViewStateEngine.php', | ||||||
|     'PhabricatorChartAxis' => 'applications/fact/chart/PhabricatorChartAxis.php', |     'PhabricatorChartAxis' => 'applications/fact/chart/PhabricatorChartAxis.php', | ||||||
|     'PhabricatorChartDataQuery' => 'applications/fact/chart/PhabricatorChartDataQuery.php', |     'PhabricatorChartDataQuery' => 'applications/fact/chart/PhabricatorChartDataQuery.php', | ||||||
|     'PhabricatorChartDataset' => 'applications/fact/chart/PhabricatorChartDataset.php', |     'PhabricatorChartDataset' => 'applications/fact/chart/PhabricatorChartDataset.php', | ||||||
| @@ -2798,46 +2828,42 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConduitTokenQuery' => 'applications/conduit/query/PhabricatorConduitTokenQuery.php', |     'PhabricatorConduitTokenQuery' => 'applications/conduit/query/PhabricatorConduitTokenQuery.php', | ||||||
|     'PhabricatorConduitTokenTerminateController' => 'applications/conduit/controller/PhabricatorConduitTokenTerminateController.php', |     'PhabricatorConduitTokenTerminateController' => 'applications/conduit/controller/PhabricatorConduitTokenTerminateController.php', | ||||||
|     'PhabricatorConduitTokensSettingsPanel' => 'applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php', |     'PhabricatorConduitTokensSettingsPanel' => 'applications/conduit/settings/PhabricatorConduitTokensSettingsPanel.php', | ||||||
|     'PhabricatorConfigAllController' => 'applications/config/controller/PhabricatorConfigAllController.php', |  | ||||||
|     'PhabricatorConfigApplication' => 'applications/config/application/PhabricatorConfigApplication.php', |     'PhabricatorConfigApplication' => 'applications/config/application/PhabricatorConfigApplication.php', | ||||||
|     'PhabricatorConfigApplicationController' => 'applications/config/controller/PhabricatorConfigApplicationController.php', |     'PhabricatorConfigCacheController' => 'applications/config/controller/services/PhabricatorConfigCacheController.php', | ||||||
|     'PhabricatorConfigCacheController' => 'applications/config/controller/PhabricatorConfigCacheController.php', |     'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/services/PhabricatorConfigClusterDatabasesController.php', | ||||||
|     'PhabricatorConfigClusterDatabasesController' => 'applications/config/controller/PhabricatorConfigClusterDatabasesController.php', |     'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/services/PhabricatorConfigClusterNotificationsController.php', | ||||||
|     'PhabricatorConfigClusterNotificationsController' => 'applications/config/controller/PhabricatorConfigClusterNotificationsController.php', |     'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/services/PhabricatorConfigClusterRepositoriesController.php', | ||||||
|     'PhabricatorConfigClusterRepositoriesController' => 'applications/config/controller/PhabricatorConfigClusterRepositoriesController.php', |     'PhabricatorConfigClusterSearchController' => 'applications/config/controller/services/PhabricatorConfigClusterSearchController.php', | ||||||
|     'PhabricatorConfigClusterSearchController' => 'applications/config/controller/PhabricatorConfigClusterSearchController.php', |  | ||||||
|     'PhabricatorConfigCollectorsModule' => 'applications/config/module/PhabricatorConfigCollectorsModule.php', |     'PhabricatorConfigCollectorsModule' => 'applications/config/module/PhabricatorConfigCollectorsModule.php', | ||||||
|     'PhabricatorConfigColumnSchema' => 'applications/config/schema/PhabricatorConfigColumnSchema.php', |     'PhabricatorConfigColumnSchema' => 'applications/config/schema/PhabricatorConfigColumnSchema.php', | ||||||
|     'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php', |     'PhabricatorConfigConfigPHIDType' => 'applications/config/phid/PhabricatorConfigConfigPHIDType.php', | ||||||
|  |     'PhabricatorConfigConsoleController' => 'applications/config/controller/PhabricatorConfigConsoleController.php', | ||||||
|     'PhabricatorConfigConstants' => 'applications/config/constants/PhabricatorConfigConstants.php', |     'PhabricatorConfigConstants' => 'applications/config/constants/PhabricatorConfigConstants.php', | ||||||
|     'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php', |     'PhabricatorConfigController' => 'applications/config/controller/PhabricatorConfigController.php', | ||||||
|     'PhabricatorConfigCoreSchemaSpec' => 'applications/config/schema/PhabricatorConfigCoreSchemaSpec.php', |     'PhabricatorConfigCoreSchemaSpec' => 'applications/config/schema/PhabricatorConfigCoreSchemaSpec.php', | ||||||
|     'PhabricatorConfigDatabaseController' => 'applications/config/controller/PhabricatorConfigDatabaseController.php', |     'PhabricatorConfigDatabaseController' => 'applications/config/controller/services/PhabricatorConfigDatabaseController.php', | ||||||
|     'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/PhabricatorConfigDatabaseIssueController.php', |     'PhabricatorConfigDatabaseIssueController' => 'applications/config/controller/services/PhabricatorConfigDatabaseIssueController.php', | ||||||
|     'PhabricatorConfigDatabaseSchema' => 'applications/config/schema/PhabricatorConfigDatabaseSchema.php', |     'PhabricatorConfigDatabaseSchema' => 'applications/config/schema/PhabricatorConfigDatabaseSchema.php', | ||||||
|     'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php', |     'PhabricatorConfigDatabaseSource' => 'infrastructure/env/PhabricatorConfigDatabaseSource.php', | ||||||
|     'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/PhabricatorConfigDatabaseStatusController.php', |     'PhabricatorConfigDatabaseStatusController' => 'applications/config/controller/services/PhabricatorConfigDatabaseStatusController.php', | ||||||
|     'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php', |     'PhabricatorConfigDefaultSource' => 'infrastructure/env/PhabricatorConfigDefaultSource.php', | ||||||
|     'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php', |     'PhabricatorConfigDictionarySource' => 'infrastructure/env/PhabricatorConfigDictionarySource.php', | ||||||
|     'PhabricatorConfigEdgeModule' => 'applications/config/module/PhabricatorConfigEdgeModule.php', |     'PhabricatorConfigEdgeModule' => 'applications/config/module/PhabricatorConfigEdgeModule.php', | ||||||
|     'PhabricatorConfigEditController' => 'applications/config/controller/PhabricatorConfigEditController.php', |     'PhabricatorConfigEditController' => 'applications/config/controller/settings/PhabricatorConfigEditController.php', | ||||||
|     'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php', |     'PhabricatorConfigEditor' => 'applications/config/editor/PhabricatorConfigEditor.php', | ||||||
|     'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php', |     'PhabricatorConfigEntry' => 'applications/config/storage/PhabricatorConfigEntry.php', | ||||||
|     'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php', |     'PhabricatorConfigEntryDAO' => 'applications/config/storage/PhabricatorConfigEntryDAO.php', | ||||||
|     'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php', |     'PhabricatorConfigEntryQuery' => 'applications/config/query/PhabricatorConfigEntryQuery.php', | ||||||
|     'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', |     'PhabricatorConfigFileSource' => 'infrastructure/env/PhabricatorConfigFileSource.php', | ||||||
|     'PhabricatorConfigGroupConstants' => 'applications/config/constants/PhabricatorConfigGroupConstants.php', |     'PhabricatorConfigGroupConstants' => 'applications/config/constants/PhabricatorConfigGroupConstants.php', | ||||||
|     'PhabricatorConfigGroupController' => 'applications/config/controller/PhabricatorConfigGroupController.php', |  | ||||||
|     'PhabricatorConfigHTTPParameterTypesModule' => 'applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php', |     'PhabricatorConfigHTTPParameterTypesModule' => 'applications/config/module/PhabricatorConfigHTTPParameterTypesModule.php', | ||||||
|     'PhabricatorConfigHistoryController' => 'applications/config/controller/PhabricatorConfigHistoryController.php', |     'PhabricatorConfigIgnoreController' => 'applications/config/controller/issue/PhabricatorConfigIgnoreController.php', | ||||||
|     'PhabricatorConfigIgnoreController' => 'applications/config/controller/PhabricatorConfigIgnoreController.php', |     'PhabricatorConfigIssueListController' => 'applications/config/controller/issue/PhabricatorConfigIssueListController.php', | ||||||
|     'PhabricatorConfigIssueListController' => 'applications/config/controller/PhabricatorConfigIssueListController.php', |     'PhabricatorConfigIssuePanelController' => 'applications/config/controller/issue/PhabricatorConfigIssuePanelController.php', | ||||||
|     'PhabricatorConfigIssuePanelController' => 'applications/config/controller/PhabricatorConfigIssuePanelController.php', |     'PhabricatorConfigIssueViewController' => 'applications/config/controller/issue/PhabricatorConfigIssueViewController.php', | ||||||
|     'PhabricatorConfigIssueViewController' => 'applications/config/controller/PhabricatorConfigIssueViewController.php', |  | ||||||
|     'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php', |     'PhabricatorConfigJSON' => 'applications/config/json/PhabricatorConfigJSON.php', | ||||||
|     'PhabricatorConfigJSONOptionType' => 'applications/config/custom/PhabricatorConfigJSONOptionType.php', |     'PhabricatorConfigJSONOptionType' => 'applications/config/custom/PhabricatorConfigJSONOptionType.php', | ||||||
|     'PhabricatorConfigKeySchema' => 'applications/config/schema/PhabricatorConfigKeySchema.php', |     'PhabricatorConfigKeySchema' => 'applications/config/schema/PhabricatorConfigKeySchema.php', | ||||||
|     'PhabricatorConfigListController' => 'applications/config/controller/PhabricatorConfigListController.php', |  | ||||||
|     'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', |     'PhabricatorConfigLocalSource' => 'infrastructure/env/PhabricatorConfigLocalSource.php', | ||||||
|     'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', |     'PhabricatorConfigManagementDeleteWorkflow' => 'applications/config/management/PhabricatorConfigManagementDeleteWorkflow.php', | ||||||
|     'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php', |     'PhabricatorConfigManagementDoneWorkflow' => 'applications/config/management/PhabricatorConfigManagementDoneWorkflow.php', | ||||||
| @@ -2848,12 +2874,12 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', |     'PhabricatorConfigManagementWorkflow' => 'applications/config/management/PhabricatorConfigManagementWorkflow.php', | ||||||
|     'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php', |     'PhabricatorConfigManualActivity' => 'applications/config/storage/PhabricatorConfigManualActivity.php', | ||||||
|     'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php', |     'PhabricatorConfigModule' => 'applications/config/module/PhabricatorConfigModule.php', | ||||||
|     'PhabricatorConfigModuleController' => 'applications/config/controller/PhabricatorConfigModuleController.php', |     'PhabricatorConfigModuleController' => 'applications/config/controller/module/PhabricatorConfigModuleController.php', | ||||||
|     'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', |     'PhabricatorConfigOption' => 'applications/config/option/PhabricatorConfigOption.php', | ||||||
|     'PhabricatorConfigOptionType' => 'applications/config/custom/PhabricatorConfigOptionType.php', |     'PhabricatorConfigOptionType' => 'applications/config/custom/PhabricatorConfigOptionType.php', | ||||||
|     'PhabricatorConfigPHIDModule' => 'applications/config/module/PhabricatorConfigPHIDModule.php', |     'PhabricatorConfigPHIDModule' => 'applications/config/module/PhabricatorConfigPHIDModule.php', | ||||||
|     'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', |     'PhabricatorConfigProxySource' => 'infrastructure/env/PhabricatorConfigProxySource.php', | ||||||
|     'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/PhabricatorConfigPurgeCacheController.php', |     'PhabricatorConfigPurgeCacheController' => 'applications/config/controller/services/PhabricatorConfigPurgeCacheController.php', | ||||||
|     'PhabricatorConfigRegexOptionType' => 'applications/config/custom/PhabricatorConfigRegexOptionType.php', |     'PhabricatorConfigRegexOptionType' => 'applications/config/custom/PhabricatorConfigRegexOptionType.php', | ||||||
|     'PhabricatorConfigRemarkupRule' => 'infrastructure/markup/rule/PhabricatorConfigRemarkupRule.php', |     'PhabricatorConfigRemarkupRule' => 'infrastructure/markup/rule/PhabricatorConfigRemarkupRule.php', | ||||||
|     'PhabricatorConfigRequestExceptionHandlerModule' => 'applications/config/module/PhabricatorConfigRequestExceptionHandlerModule.php', |     'PhabricatorConfigRequestExceptionHandlerModule' => 'applications/config/module/PhabricatorConfigRequestExceptionHandlerModule.php', | ||||||
| @@ -2861,6 +2887,10 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php', |     'PhabricatorConfigSchemaQuery' => 'applications/config/schema/PhabricatorConfigSchemaQuery.php', | ||||||
|     'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php', |     'PhabricatorConfigSchemaSpec' => 'applications/config/schema/PhabricatorConfigSchemaSpec.php', | ||||||
|     'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php', |     'PhabricatorConfigServerSchema' => 'applications/config/schema/PhabricatorConfigServerSchema.php', | ||||||
|  |     'PhabricatorConfigServicesController' => 'applications/config/controller/services/PhabricatorConfigServicesController.php', | ||||||
|  |     'PhabricatorConfigSettingsController' => 'applications/config/controller/settings/PhabricatorConfigSettingsController.php', | ||||||
|  |     'PhabricatorConfigSettingsHistoryController' => 'applications/config/controller/settings/PhabricatorConfigSettingsHistoryController.php', | ||||||
|  |     'PhabricatorConfigSettingsListController' => 'applications/config/controller/settings/PhabricatorConfigSettingsListController.php', | ||||||
|     'PhabricatorConfigSetupCheckModule' => 'applications/config/module/PhabricatorConfigSetupCheckModule.php', |     'PhabricatorConfigSetupCheckModule' => 'applications/config/module/PhabricatorConfigSetupCheckModule.php', | ||||||
|     'PhabricatorConfigSiteModule' => 'applications/config/module/PhabricatorConfigSiteModule.php', |     'PhabricatorConfigSiteModule' => 'applications/config/module/PhabricatorConfigSiteModule.php', | ||||||
|     'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php', |     'PhabricatorConfigSiteSource' => 'infrastructure/env/PhabricatorConfigSiteSource.php', | ||||||
| @@ -2872,7 +2902,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php', |     'PhabricatorConfigTransactionQuery' => 'applications/config/query/PhabricatorConfigTransactionQuery.php', | ||||||
|     'PhabricatorConfigType' => 'applications/config/type/PhabricatorConfigType.php', |     'PhabricatorConfigType' => 'applications/config/type/PhabricatorConfigType.php', | ||||||
|     'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php', |     'PhabricatorConfigValidationException' => 'applications/config/exception/PhabricatorConfigValidationException.php', | ||||||
|     'PhabricatorConfigVersionController' => 'applications/config/controller/PhabricatorConfigVersionController.php', |  | ||||||
|     'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php', |     'PhabricatorConpherenceApplication' => 'applications/conpherence/application/PhabricatorConpherenceApplication.php', | ||||||
|     'PhabricatorConpherenceColumnMinimizeSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnMinimizeSetting.php', |     'PhabricatorConpherenceColumnMinimizeSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnMinimizeSetting.php', | ||||||
|     'PhabricatorConpherenceColumnVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnVisibleSetting.php', |     'PhabricatorConpherenceColumnVisibleSetting' => 'applications/settings/setting/PhabricatorConpherenceColumnVisibleSetting.php', | ||||||
| @@ -3134,6 +3163,8 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorDestructionEngineExtensionModule' => 'applications/system/engine/PhabricatorDestructionEngineExtensionModule.php', |     'PhabricatorDestructionEngineExtensionModule' => 'applications/system/engine/PhabricatorDestructionEngineExtensionModule.php', | ||||||
|     'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php', |     'PhabricatorDeveloperConfigOptions' => 'applications/config/option/PhabricatorDeveloperConfigOptions.php', | ||||||
|     'PhabricatorDeveloperPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDeveloperPreferencesSettingsPanel.php', |     'PhabricatorDeveloperPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDeveloperPreferencesSettingsPanel.php', | ||||||
|  |     'PhabricatorDiffInlineCommentContentState' => 'infrastructure/diff/inline/PhabricatorDiffInlineCommentContentState.php', | ||||||
|  |     'PhabricatorDiffInlineCommentContext' => 'infrastructure/diff/inline/PhabricatorDiffInlineCommentContext.php', | ||||||
|     'PhabricatorDiffInlineCommentQuery' => 'infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php', |     'PhabricatorDiffInlineCommentQuery' => 'infrastructure/diff/query/PhabricatorDiffInlineCommentQuery.php', | ||||||
|     'PhabricatorDiffPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDiffPreferencesSettingsPanel.php', |     'PhabricatorDiffPreferencesSettingsPanel' => 'applications/settings/panel/PhabricatorDiffPreferencesSettingsPanel.php', | ||||||
|     'PhabricatorDiffScopeEngine' => 'infrastructure/diff/PhabricatorDiffScopeEngine.php', |     'PhabricatorDiffScopeEngine' => 'infrastructure/diff/PhabricatorDiffScopeEngine.php', | ||||||
| @@ -3233,6 +3264,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorEditEngineMFAInterface' => 'applications/transactions/editengine/PhabricatorEditEngineMFAInterface.php', |     'PhabricatorEditEngineMFAInterface' => 'applications/transactions/editengine/PhabricatorEditEngineMFAInterface.php', | ||||||
|     'PhabricatorEditEngineNameTransaction' => 'applications/transactions/xaction/PhabricatorEditEngineNameTransaction.php', |     'PhabricatorEditEngineNameTransaction' => 'applications/transactions/xaction/PhabricatorEditEngineNameTransaction.php', | ||||||
|     'PhabricatorEditEngineOrderTransaction' => 'applications/transactions/xaction/PhabricatorEditEngineOrderTransaction.php', |     'PhabricatorEditEngineOrderTransaction' => 'applications/transactions/xaction/PhabricatorEditEngineOrderTransaction.php', | ||||||
|  |     'PhabricatorEditEnginePageState' => 'applications/transactions/editengine/PhabricatorEditEnginePageState.php', | ||||||
|     'PhabricatorEditEnginePointsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEnginePointsCommentAction.php', |     'PhabricatorEditEnginePointsCommentAction' => 'applications/transactions/commentaction/PhabricatorEditEnginePointsCommentAction.php', | ||||||
|     'PhabricatorEditEnginePreambleTransaction' => 'applications/transactions/xaction/PhabricatorEditEnginePreambleTransaction.php', |     'PhabricatorEditEnginePreambleTransaction' => 'applications/transactions/xaction/PhabricatorEditEnginePreambleTransaction.php', | ||||||
|     'PhabricatorEditEngineProfileMenuItem' => 'applications/search/menuitem/PhabricatorEditEngineProfileMenuItem.php', |     'PhabricatorEditEngineProfileMenuItem' => 'applications/search/menuitem/PhabricatorEditEngineProfileMenuItem.php', | ||||||
| @@ -3256,8 +3288,10 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorEditorExtension' => 'applications/transactions/engineextension/PhabricatorEditorExtension.php', |     'PhabricatorEditorExtension' => 'applications/transactions/engineextension/PhabricatorEditorExtension.php', | ||||||
|     'PhabricatorEditorExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditorExtensionModule.php', |     'PhabricatorEditorExtensionModule' => 'applications/transactions/engineextension/PhabricatorEditorExtensionModule.php', | ||||||
|     'PhabricatorEditorMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditorMailEngineExtension.php', |     'PhabricatorEditorMailEngineExtension' => 'applications/transactions/engineextension/PhabricatorEditorMailEngineExtension.php', | ||||||
|     'PhabricatorEditorMultipleSetting' => 'applications/settings/setting/PhabricatorEditorMultipleSetting.php', |  | ||||||
|     'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php', |     'PhabricatorEditorSetting' => 'applications/settings/setting/PhabricatorEditorSetting.php', | ||||||
|  |     'PhabricatorEditorURIEngine' => 'infrastructure/editor/PhabricatorEditorURIEngine.php', | ||||||
|  |     'PhabricatorEditorURIEngineTestCase' => 'infrastructure/editor/__tests__/PhabricatorEditorURIEngineTestCase.php', | ||||||
|  |     'PhabricatorEditorURIParserException' => 'infrastructure/editor/PhabricatorEditorURIParserException.php', | ||||||
|     'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php', |     'PhabricatorElasticFulltextStorageEngine' => 'applications/search/fulltextstorage/PhabricatorElasticFulltextStorageEngine.php', | ||||||
|     'PhabricatorElasticsearchHost' => 'infrastructure/cluster/search/PhabricatorElasticsearchHost.php', |     'PhabricatorElasticsearchHost' => 'infrastructure/cluster/search/PhabricatorElasticsearchHost.php', | ||||||
|     'PhabricatorElasticsearchQueryBuilder' => 'applications/search/fulltextstorage/PhabricatorElasticsearchQueryBuilder.php', |     'PhabricatorElasticsearchQueryBuilder' => 'applications/search/fulltextstorage/PhabricatorElasticsearchQueryBuilder.php', | ||||||
| @@ -3306,8 +3340,11 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php', |     'PhabricatorExtendingPhabricatorConfigOptions' => 'applications/config/option/PhabricatorExtendingPhabricatorConfigOptions.php', | ||||||
|     'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php', |     'PhabricatorExtensionsSetupCheck' => 'applications/config/check/PhabricatorExtensionsSetupCheck.php', | ||||||
|     'PhabricatorExternalAccount' => 'applications/people/storage/PhabricatorExternalAccount.php', |     'PhabricatorExternalAccount' => 'applications/people/storage/PhabricatorExternalAccount.php', | ||||||
|  |     'PhabricatorExternalAccountIdentifier' => 'applications/people/storage/PhabricatorExternalAccountIdentifier.php', | ||||||
|  |     'PhabricatorExternalAccountIdentifierQuery' => 'applications/auth/query/PhabricatorExternalAccountIdentifierQuery.php', | ||||||
|     'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php', |     'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php', | ||||||
|     'PhabricatorExternalAccountsSettingsPanel' => 'applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php', |     'PhabricatorExternalAccountsSettingsPanel' => 'applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php', | ||||||
|  |     'PhabricatorExternalEditorSettingsPanel' => 'applications/settings/panel/PhabricatorExternalEditorSettingsPanel.php', | ||||||
|     'PhabricatorExtraConfigSetupCheck' => 'applications/config/check/PhabricatorExtraConfigSetupCheck.php', |     'PhabricatorExtraConfigSetupCheck' => 'applications/config/check/PhabricatorExtraConfigSetupCheck.php', | ||||||
|     'PhabricatorFacebookAuthProvider' => 'applications/auth/provider/PhabricatorFacebookAuthProvider.php', |     'PhabricatorFacebookAuthProvider' => 'applications/auth/provider/PhabricatorFacebookAuthProvider.php', | ||||||
|     'PhabricatorFact' => 'applications/fact/fact/PhabricatorFact.php', |     'PhabricatorFact' => 'applications/fact/fact/PhabricatorFact.php', | ||||||
| @@ -3337,6 +3374,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php', |     'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php', | ||||||
|     'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', |     'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php', | ||||||
|     'PhabricatorFailHisecUserLogType' => 'applications/people/userlog/PhabricatorFailHisecUserLogType.php', |     'PhabricatorFailHisecUserLogType' => 'applications/people/userlog/PhabricatorFailHisecUserLogType.php', | ||||||
|  |     'PhabricatorFaviconController' => 'applications/system/controller/PhabricatorFaviconController.php', | ||||||
|     'PhabricatorFaviconRef' => 'applications/files/favicon/PhabricatorFaviconRef.php', |     'PhabricatorFaviconRef' => 'applications/files/favicon/PhabricatorFaviconRef.php', | ||||||
|     'PhabricatorFaviconRefQuery' => 'applications/files/favicon/PhabricatorFaviconRefQuery.php', |     'PhabricatorFaviconRefQuery' => 'applications/files/favicon/PhabricatorFaviconRefQuery.php', | ||||||
|     'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php', |     'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php', | ||||||
| @@ -3523,7 +3561,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorHelpApplication' => 'applications/help/application/PhabricatorHelpApplication.php', |     'PhabricatorHelpApplication' => 'applications/help/application/PhabricatorHelpApplication.php', | ||||||
|     'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php', |     'PhabricatorHelpController' => 'applications/help/controller/PhabricatorHelpController.php', | ||||||
|     'PhabricatorHelpDocumentationController' => 'applications/help/controller/PhabricatorHelpDocumentationController.php', |     'PhabricatorHelpDocumentationController' => 'applications/help/controller/PhabricatorHelpDocumentationController.php', | ||||||
|     'PhabricatorHelpEditorProtocolController' => 'applications/help/controller/PhabricatorHelpEditorProtocolController.php', |  | ||||||
|     'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', |     'PhabricatorHelpKeyboardShortcutController' => 'applications/help/controller/PhabricatorHelpKeyboardShortcutController.php', | ||||||
|     'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php', |     'PhabricatorHeraldApplication' => 'applications/herald/application/PhabricatorHeraldApplication.php', | ||||||
|     'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php', |     'PhabricatorHeraldContentSource' => 'applications/herald/contentsource/PhabricatorHeraldContentSource.php', | ||||||
| @@ -3558,9 +3595,12 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorIndexEngineExtensionModule' => 'applications/search/index/PhabricatorIndexEngineExtensionModule.php', |     'PhabricatorIndexEngineExtensionModule' => 'applications/search/index/PhabricatorIndexEngineExtensionModule.php', | ||||||
|     'PhabricatorIndexableInterface' => 'applications/search/interface/PhabricatorIndexableInterface.php', |     'PhabricatorIndexableInterface' => 'applications/search/interface/PhabricatorIndexableInterface.php', | ||||||
|     'PhabricatorInfrastructureTestCase' => '__tests__/PhabricatorInfrastructureTestCase.php', |     'PhabricatorInfrastructureTestCase' => '__tests__/PhabricatorInfrastructureTestCase.php', | ||||||
|  |     'PhabricatorInlineComment' => 'infrastructure/diff/interface/PhabricatorInlineComment.php', | ||||||
|  |     'PhabricatorInlineCommentAdjustmentEngine' => 'infrastructure/diff/engine/PhabricatorInlineCommentAdjustmentEngine.php', | ||||||
|  |     'PhabricatorInlineCommentContentState' => 'infrastructure/diff/inline/PhabricatorInlineCommentContentState.php', | ||||||
|  |     'PhabricatorInlineCommentContext' => 'infrastructure/diff/inline/PhabricatorInlineCommentContext.php', | ||||||
|     'PhabricatorInlineCommentController' => 'infrastructure/diff/PhabricatorInlineCommentController.php', |     'PhabricatorInlineCommentController' => 'infrastructure/diff/PhabricatorInlineCommentController.php', | ||||||
|     'PhabricatorInlineCommentInterface' => 'infrastructure/diff/interface/PhabricatorInlineCommentInterface.php', |     'PhabricatorInlineCommentInterface' => 'applications/transactions/interface/PhabricatorInlineCommentInterface.php', | ||||||
|     'PhabricatorInlineCommentPreviewController' => 'infrastructure/diff/PhabricatorInlineCommentPreviewController.php', |  | ||||||
|     'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php', |     'PhabricatorInlineSummaryView' => 'infrastructure/diff/view/PhabricatorInlineSummaryView.php', | ||||||
|     'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php', |     'PhabricatorInstructionsEditField' => 'applications/transactions/editfield/PhabricatorInstructionsEditField.php', | ||||||
|     'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php', |     'PhabricatorIntConfigType' => 'applications/config/type/PhabricatorIntConfigType.php', | ||||||
| @@ -4056,7 +4096,9 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPasteEditController' => 'applications/paste/controller/PhabricatorPasteEditController.php', |     'PhabricatorPasteEditController' => 'applications/paste/controller/PhabricatorPasteEditController.php', | ||||||
|     'PhabricatorPasteEditEngine' => 'applications/paste/editor/PhabricatorPasteEditEngine.php', |     'PhabricatorPasteEditEngine' => 'applications/paste/editor/PhabricatorPasteEditEngine.php', | ||||||
|     'PhabricatorPasteEditor' => 'applications/paste/editor/PhabricatorPasteEditor.php', |     'PhabricatorPasteEditor' => 'applications/paste/editor/PhabricatorPasteEditor.php', | ||||||
|  |     'PhabricatorPasteFerretEngine' => 'applications/paste/engine/PhabricatorPasteFerretEngine.php', | ||||||
|     'PhabricatorPasteFilenameContextFreeGrammar' => 'applications/paste/lipsum/PhabricatorPasteFilenameContextFreeGrammar.php', |     'PhabricatorPasteFilenameContextFreeGrammar' => 'applications/paste/lipsum/PhabricatorPasteFilenameContextFreeGrammar.php', | ||||||
|  |     'PhabricatorPasteFulltextEngine' => 'applications/paste/engine/PhabricatorPasteFulltextEngine.php', | ||||||
|     'PhabricatorPasteLanguageTransaction' => 'applications/paste/xaction/PhabricatorPasteLanguageTransaction.php', |     'PhabricatorPasteLanguageTransaction' => 'applications/paste/xaction/PhabricatorPasteLanguageTransaction.php', | ||||||
|     'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php', |     'PhabricatorPasteListController' => 'applications/paste/controller/PhabricatorPasteListController.php', | ||||||
|     'PhabricatorPastePastePHIDType' => 'applications/paste/phid/PhabricatorPastePastePHIDType.php', |     'PhabricatorPastePastePHIDType' => 'applications/paste/phid/PhabricatorPastePastePHIDType.php', | ||||||
| @@ -4091,6 +4133,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', |     'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php', | ||||||
|     'PhabricatorPeopleEmailLoginMailEngine' => 'applications/people/mail/PhabricatorPeopleEmailLoginMailEngine.php', |     'PhabricatorPeopleEmailLoginMailEngine' => 'applications/people/mail/PhabricatorPeopleEmailLoginMailEngine.php', | ||||||
|     'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', |     'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php', | ||||||
|  |     'PhabricatorPeopleExternalIdentifierPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalIdentifierPHIDType.php', | ||||||
|     'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', |     'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php', | ||||||
|     'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php', |     'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php', | ||||||
|     'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php', |     'PhabricatorPeopleInviteController' => 'applications/people/controller/PhabricatorPeopleInviteController.php', | ||||||
| @@ -4125,6 +4168,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', |     'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php', | ||||||
|     'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php', |     'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php', | ||||||
|     'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', |     'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php', | ||||||
|  |     'PhabricatorPeopleSpamController' => 'applications/people/controller/PhabricatorPeopleSpamController.php', | ||||||
|     'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php', |     'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php', | ||||||
|     'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', |     'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php', | ||||||
|     'PhabricatorPeopleTransactionQuery' => 'applications/people/query/PhabricatorPeopleTransactionQuery.php', |     'PhabricatorPeopleTransactionQuery' => 'applications/people/query/PhabricatorPeopleTransactionQuery.php', | ||||||
| @@ -4679,6 +4723,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSearchManagementNgramsWorkflow' => 'applications/search/management/PhabricatorSearchManagementNgramsWorkflow.php', |     'PhabricatorSearchManagementNgramsWorkflow' => 'applications/search/management/PhabricatorSearchManagementNgramsWorkflow.php', | ||||||
|     'PhabricatorSearchManagementQueryWorkflow' => 'applications/search/management/PhabricatorSearchManagementQueryWorkflow.php', |     'PhabricatorSearchManagementQueryWorkflow' => 'applications/search/management/PhabricatorSearchManagementQueryWorkflow.php', | ||||||
|     'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php', |     'PhabricatorSearchManagementWorkflow' => 'applications/search/management/PhabricatorSearchManagementWorkflow.php', | ||||||
|  |     'PhabricatorSearchNgramEngine' => 'applications/search/engine/PhabricatorSearchNgramEngine.php', | ||||||
|     'PhabricatorSearchNgrams' => 'applications/search/ngrams/PhabricatorSearchNgrams.php', |     'PhabricatorSearchNgrams' => 'applications/search/ngrams/PhabricatorSearchNgrams.php', | ||||||
|     'PhabricatorSearchNgramsDestructionEngineExtension' => 'applications/search/engineextension/PhabricatorSearchNgramsDestructionEngineExtension.php', |     'PhabricatorSearchNgramsDestructionEngineExtension' => 'applications/search/engineextension/PhabricatorSearchNgramsDestructionEngineExtension.php', | ||||||
|     'PhabricatorSearchOrderController' => 'applications/search/controller/PhabricatorSearchOrderController.php', |     'PhabricatorSearchOrderController' => 'applications/search/controller/PhabricatorSearchOrderController.php', | ||||||
| @@ -4722,6 +4767,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php', |     'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php', | ||||||
|     'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', |     'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', | ||||||
|     'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', |     'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', | ||||||
|  |     'PhabricatorSettingsPanelChangeUsername' => 'applications/settings/panel/PhabricatorSettingsPanelChangeUsername.php', | ||||||
|     'PhabricatorSettingsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsPanelGroup.php', |     'PhabricatorSettingsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsPanelGroup.php', | ||||||
|     'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php', |     'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php', | ||||||
|     'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', |     'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', | ||||||
| @@ -4732,7 +4778,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php', |     'PhabricatorSetupIssueView' => 'applications/config/view/PhabricatorSetupIssueView.php', | ||||||
|     'PhabricatorShiftChartFunction' => 'applications/fact/chart/PhabricatorShiftChartFunction.php', |     'PhabricatorShiftChartFunction' => 'applications/fact/chart/PhabricatorShiftChartFunction.php', | ||||||
|     'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php', |     'PhabricatorShortSite' => 'aphront/site/PhabricatorShortSite.php', | ||||||
|     'PhabricatorShowFiletreeSetting' => 'applications/settings/setting/PhabricatorShowFiletreeSetting.php', |  | ||||||
|     'PhabricatorSignDocumentsUserLogType' => 'applications/people/userlog/PhabricatorSignDocumentsUserLogType.php', |     'PhabricatorSignDocumentsUserLogType' => 'applications/people/userlog/PhabricatorSignDocumentsUserLogType.php', | ||||||
|     'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php', |     'PhabricatorSimpleEditType' => 'applications/transactions/edittype/PhabricatorSimpleEditType.php', | ||||||
|     'PhabricatorSinChartFunction' => 'applications/fact/chart/PhabricatorSinChartFunction.php', |     'PhabricatorSinChartFunction' => 'applications/fact/chart/PhabricatorSinChartFunction.php', | ||||||
| @@ -4957,6 +5002,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorTransactionChange' => 'applications/transactions/data/PhabricatorTransactionChange.php', |     'PhabricatorTransactionChange' => 'applications/transactions/data/PhabricatorTransactionChange.php', | ||||||
|     'PhabricatorTransactionFactEngine' => 'applications/fact/engine/PhabricatorTransactionFactEngine.php', |     'PhabricatorTransactionFactEngine' => 'applications/fact/engine/PhabricatorTransactionFactEngine.php', | ||||||
|     'PhabricatorTransactionRemarkupChange' => 'applications/transactions/data/PhabricatorTransactionRemarkupChange.php', |     'PhabricatorTransactionRemarkupChange' => 'applications/transactions/data/PhabricatorTransactionRemarkupChange.php', | ||||||
|  |     'PhabricatorTransactionWarning' => 'applications/transactions/data/PhabricatorTransactionWarning.php', | ||||||
|     'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php', |     'PhabricatorTransactions' => 'applications/transactions/constants/PhabricatorTransactions.php', | ||||||
|     'PhabricatorTransactionsApplication' => 'applications/transactions/application/PhabricatorTransactionsApplication.php', |     'PhabricatorTransactionsApplication' => 'applications/transactions/application/PhabricatorTransactionsApplication.php', | ||||||
|     'PhabricatorTransactionsDestructionEngineExtension' => 'applications/transactions/engineextension/PhabricatorTransactionsDestructionEngineExtension.php', |     'PhabricatorTransactionsDestructionEngineExtension' => 'applications/transactions/engineextension/PhabricatorTransactionsDestructionEngineExtension.php', | ||||||
| @@ -5015,6 +5061,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorUserCustomFieldNumericIndex' => 'applications/people/storage/PhabricatorUserCustomFieldNumericIndex.php', |     'PhabricatorUserCustomFieldNumericIndex' => 'applications/people/storage/PhabricatorUserCustomFieldNumericIndex.php', | ||||||
|     'PhabricatorUserCustomFieldStringIndex' => 'applications/people/storage/PhabricatorUserCustomFieldStringIndex.php', |     'PhabricatorUserCustomFieldStringIndex' => 'applications/people/storage/PhabricatorUserCustomFieldStringIndex.php', | ||||||
|     'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php', |     'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php', | ||||||
|  |     'PhabricatorUserDisableSpamTransaction' => 'applications/people/xaction/PhabricatorUserDisableSpamTransaction.php', | ||||||
|     'PhabricatorUserDisableTransaction' => 'applications/people/xaction/PhabricatorUserDisableTransaction.php', |     'PhabricatorUserDisableTransaction' => 'applications/people/xaction/PhabricatorUserDisableTransaction.php', | ||||||
|     'PhabricatorUserEditEngine' => 'applications/people/editor/PhabricatorUserEditEngine.php', |     'PhabricatorUserEditEngine' => 'applications/people/editor/PhabricatorUserEditEngine.php', | ||||||
|     'PhabricatorUserEditor' => 'applications/people/editor/PhabricatorUserEditor.php', |     'PhabricatorUserEditor' => 'applications/people/editor/PhabricatorUserEditor.php', | ||||||
| @@ -5580,6 +5627,7 @@ phutil_register_library_map(array( | |||||||
|     'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php', |     'PhrictionTransactionComment' => 'applications/phriction/storage/PhrictionTransactionComment.php', | ||||||
|     'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php', |     'PhrictionTransactionEditor' => 'applications/phriction/editor/PhrictionTransactionEditor.php', | ||||||
|     'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php', |     'PhrictionTransactionQuery' => 'applications/phriction/query/PhrictionTransactionQuery.php', | ||||||
|  |     'PhutilAPCKeyValueCache' => 'infrastructure/cache/PhutilAPCKeyValueCache.php', | ||||||
|     'PhutilAmazonAuthAdapter' => 'applications/auth/adapter/PhutilAmazonAuthAdapter.php', |     'PhutilAmazonAuthAdapter' => 'applications/auth/adapter/PhutilAmazonAuthAdapter.php', | ||||||
|     'PhutilAsanaAuthAdapter' => 'applications/auth/adapter/PhutilAsanaAuthAdapter.php', |     'PhutilAsanaAuthAdapter' => 'applications/auth/adapter/PhutilAsanaAuthAdapter.php', | ||||||
|     'PhutilAuthAdapter' => 'applications/auth/adapter/PhutilAuthAdapter.php', |     'PhutilAuthAdapter' => 'applications/auth/adapter/PhutilAuthAdapter.php', | ||||||
| @@ -5609,7 +5657,20 @@ phutil_register_library_map(array( | |||||||
|     'PhutilCalendarRootNode' => 'applications/calendar/parser/data/PhutilCalendarRootNode.php', |     'PhutilCalendarRootNode' => 'applications/calendar/parser/data/PhutilCalendarRootNode.php', | ||||||
|     'PhutilCalendarUserNode' => 'applications/calendar/parser/data/PhutilCalendarUserNode.php', |     'PhutilCalendarUserNode' => 'applications/calendar/parser/data/PhutilCalendarUserNode.php', | ||||||
|     'PhutilCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilCodeSnippetContextFreeGrammar.php', |     'PhutilCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilCodeSnippetContextFreeGrammar.php', | ||||||
|  |     'PhutilConsoleSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilConsoleSyntaxHighlighter.php', | ||||||
|  |     'PhutilContextFreeGrammar' => 'infrastructure/lipsum/PhutilContextFreeGrammar.php', | ||||||
|  |     'PhutilDaemon' => 'infrastructure/daemon/PhutilDaemon.php', | ||||||
|  |     'PhutilDaemonHandle' => 'infrastructure/daemon/PhutilDaemonHandle.php', | ||||||
|  |     'PhutilDaemonOverseer' => 'infrastructure/daemon/PhutilDaemonOverseer.php', | ||||||
|  |     'PhutilDaemonOverseerModule' => 'infrastructure/daemon/PhutilDaemonOverseerModule.php', | ||||||
|  |     'PhutilDaemonPool' => 'infrastructure/daemon/PhutilDaemonPool.php', | ||||||
|  |     'PhutilDefaultSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilDefaultSyntaxHighlighter.php', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEngine' => 'infrastructure/markup/syntax/engine/PhutilDefaultSyntaxHighlighterEngine.php', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEnginePygmentsFuture' => 'infrastructure/markup/syntax/highlighter/pygments/PhutilDefaultSyntaxHighlighterEnginePygmentsFuture.php', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEngineTestCase' => 'infrastructure/markup/syntax/engine/__tests__/PhutilDefaultSyntaxHighlighterEngineTestCase.php', | ||||||
|  |     'PhutilDirectoryKeyValueCache' => 'infrastructure/cache/PhutilDirectoryKeyValueCache.php', | ||||||
|     'PhutilDisqusAuthAdapter' => 'applications/auth/adapter/PhutilDisqusAuthAdapter.php', |     'PhutilDisqusAuthAdapter' => 'applications/auth/adapter/PhutilDisqusAuthAdapter.php', | ||||||
|  |     'PhutilDivinerSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilDivinerSyntaxHighlighter.php', | ||||||
|     'PhutilEmptyAuthAdapter' => 'applications/auth/adapter/PhutilEmptyAuthAdapter.php', |     'PhutilEmptyAuthAdapter' => 'applications/auth/adapter/PhutilEmptyAuthAdapter.php', | ||||||
|     'PhutilFacebookAuthAdapter' => 'applications/auth/adapter/PhutilFacebookAuthAdapter.php', |     'PhutilFacebookAuthAdapter' => 'applications/auth/adapter/PhutilFacebookAuthAdapter.php', | ||||||
|     'PhutilGitHubAuthAdapter' => 'applications/auth/adapter/PhutilGitHubAuthAdapter.php', |     'PhutilGitHubAuthAdapter' => 'applications/auth/adapter/PhutilGitHubAuthAdapter.php', | ||||||
| @@ -5619,19 +5680,38 @@ phutil_register_library_map(array( | |||||||
|     'PhutilICSParserTestCase' => 'applications/calendar/parser/ics/__tests__/PhutilICSParserTestCase.php', |     'PhutilICSParserTestCase' => 'applications/calendar/parser/ics/__tests__/PhutilICSParserTestCase.php', | ||||||
|     'PhutilICSWriter' => 'applications/calendar/parser/ics/PhutilICSWriter.php', |     'PhutilICSWriter' => 'applications/calendar/parser/ics/PhutilICSWriter.php', | ||||||
|     'PhutilICSWriterTestCase' => 'applications/calendar/parser/ics/__tests__/PhutilICSWriterTestCase.php', |     'PhutilICSWriterTestCase' => 'applications/calendar/parser/ics/__tests__/PhutilICSWriterTestCase.php', | ||||||
|  |     'PhutilInRequestKeyValueCache' => 'infrastructure/cache/PhutilInRequestKeyValueCache.php', | ||||||
|  |     'PhutilInvisibleSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilInvisibleSyntaxHighlighter.php', | ||||||
|     'PhutilJIRAAuthAdapter' => 'applications/auth/adapter/PhutilJIRAAuthAdapter.php', |     'PhutilJIRAAuthAdapter' => 'applications/auth/adapter/PhutilJIRAAuthAdapter.php', | ||||||
|  |     'PhutilJSONFragmentLexerHighlighterTestCase' => 'infrastructure/markup/syntax/highlighter/__tests__/PhutilJSONFragmentLexerHighlighterTestCase.php', | ||||||
|     'PhutilJavaCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilJavaCodeSnippetContextFreeGrammar.php', |     'PhutilJavaCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilJavaCodeSnippetContextFreeGrammar.php', | ||||||
|  |     'PhutilKeyValueCache' => 'infrastructure/cache/PhutilKeyValueCache.php', | ||||||
|  |     'PhutilKeyValueCacheNamespace' => 'infrastructure/cache/PhutilKeyValueCacheNamespace.php', | ||||||
|  |     'PhutilKeyValueCacheProfiler' => 'infrastructure/cache/PhutilKeyValueCacheProfiler.php', | ||||||
|  |     'PhutilKeyValueCacheProxy' => 'infrastructure/cache/PhutilKeyValueCacheProxy.php', | ||||||
|  |     'PhutilKeyValueCacheStack' => 'infrastructure/cache/PhutilKeyValueCacheStack.php', | ||||||
|  |     'PhutilKeyValueCacheTestCase' => 'infrastructure/cache/__tests__/PhutilKeyValueCacheTestCase.php', | ||||||
|     'PhutilLDAPAuthAdapter' => 'applications/auth/adapter/PhutilLDAPAuthAdapter.php', |     'PhutilLDAPAuthAdapter' => 'applications/auth/adapter/PhutilLDAPAuthAdapter.php', | ||||||
|  |     'PhutilLexerSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilLexerSyntaxHighlighter.php', | ||||||
|     'PhutilLipsumContextFreeGrammar' => 'infrastructure/lipsum/PhutilLipsumContextFreeGrammar.php', |     'PhutilLipsumContextFreeGrammar' => 'infrastructure/lipsum/PhutilLipsumContextFreeGrammar.php', | ||||||
|  |     'PhutilMarkupEngine' => 'infrastructure/markup/PhutilMarkupEngine.php', | ||||||
|  |     'PhutilMarkupTestCase' => 'infrastructure/markup/__tests__/PhutilMarkupTestCase.php', | ||||||
|  |     'PhutilMemcacheKeyValueCache' => 'infrastructure/cache/PhutilMemcacheKeyValueCache.php', | ||||||
|     'PhutilOAuth1AuthAdapter' => 'applications/auth/adapter/PhutilOAuth1AuthAdapter.php', |     'PhutilOAuth1AuthAdapter' => 'applications/auth/adapter/PhutilOAuth1AuthAdapter.php', | ||||||
|     'PhutilOAuthAuthAdapter' => 'applications/auth/adapter/PhutilOAuthAuthAdapter.php', |     'PhutilOAuthAuthAdapter' => 'applications/auth/adapter/PhutilOAuthAuthAdapter.php', | ||||||
|  |     'PhutilOnDiskKeyValueCache' => 'infrastructure/cache/PhutilOnDiskKeyValueCache.php', | ||||||
|     'PhutilPHPCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilPHPCodeSnippetContextFreeGrammar.php', |     'PhutilPHPCodeSnippetContextFreeGrammar' => 'infrastructure/lipsum/code/PhutilPHPCodeSnippetContextFreeGrammar.php', | ||||||
|  |     'PhutilPHPFragmentLexerHighlighterTestCase' => 'infrastructure/markup/syntax/highlighter/__tests__/PhutilPHPFragmentLexerHighlighterTestCase.php', | ||||||
|     'PhutilPhabricatorAuthAdapter' => 'applications/auth/adapter/PhutilPhabricatorAuthAdapter.php', |     'PhutilPhabricatorAuthAdapter' => 'applications/auth/adapter/PhutilPhabricatorAuthAdapter.php', | ||||||
|     'PhutilProseDiff' => 'infrastructure/diff/prose/PhutilProseDiff.php', |     'PhutilProseDiff' => 'infrastructure/diff/prose/PhutilProseDiff.php', | ||||||
|     'PhutilProseDiffTestCase' => 'infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php', |     'PhutilProseDiffTestCase' => 'infrastructure/diff/prose/__tests__/PhutilProseDiffTestCase.php', | ||||||
|     'PhutilProseDifferenceEngine' => 'infrastructure/diff/prose/PhutilProseDifferenceEngine.php', |     'PhutilProseDifferenceEngine' => 'infrastructure/diff/prose/PhutilProseDifferenceEngine.php', | ||||||
|  |     'PhutilPygmentizeParser' => 'infrastructure/parser/PhutilPygmentizeParser.php', | ||||||
|  |     'PhutilPygmentizeParserTestCase' => 'infrastructure/parser/__tests__/PhutilPygmentizeParserTestCase.php', | ||||||
|  |     'PhutilPygmentsSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilPygmentsSyntaxHighlighter.php', | ||||||
|     'PhutilQsprintfInterface' => 'infrastructure/storage/xsprintf/PhutilQsprintfInterface.php', |     'PhutilQsprintfInterface' => 'infrastructure/storage/xsprintf/PhutilQsprintfInterface.php', | ||||||
|     'PhutilQueryString' => 'infrastructure/storage/xsprintf/PhutilQueryString.php', |     'PhutilQueryString' => 'infrastructure/storage/xsprintf/PhutilQueryString.php', | ||||||
|  |     'PhutilRainbowSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilRainbowSyntaxHighlighter.php', | ||||||
|     'PhutilRealNameContextFreeGrammar' => 'infrastructure/lipsum/PhutilRealNameContextFreeGrammar.php', |     'PhutilRealNameContextFreeGrammar' => 'infrastructure/lipsum/PhutilRealNameContextFreeGrammar.php', | ||||||
|     'PhutilRemarkupAnchorRule' => 'infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php', |     'PhutilRemarkupAnchorRule' => 'infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php', | ||||||
|     'PhutilRemarkupBlockInterpreter' => 'infrastructure/markup/blockrule/PhutilRemarkupBlockInterpreter.php', |     'PhutilRemarkupBlockInterpreter' => 'infrastructure/markup/blockrule/PhutilRemarkupBlockInterpreter.php', | ||||||
| @@ -5667,6 +5747,9 @@ phutil_register_library_map(array( | |||||||
|     'PhutilRemarkupTableBlockRule' => 'infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php', |     'PhutilRemarkupTableBlockRule' => 'infrastructure/markup/blockrule/PhutilRemarkupTableBlockRule.php', | ||||||
|     'PhutilRemarkupTestInterpreterRule' => 'infrastructure/markup/blockrule/PhutilRemarkupTestInterpreterRule.php', |     'PhutilRemarkupTestInterpreterRule' => 'infrastructure/markup/blockrule/PhutilRemarkupTestInterpreterRule.php', | ||||||
|     'PhutilRemarkupUnderlineRule' => 'infrastructure/markup/markuprule/PhutilRemarkupUnderlineRule.php', |     'PhutilRemarkupUnderlineRule' => 'infrastructure/markup/markuprule/PhutilRemarkupUnderlineRule.php', | ||||||
|  |     'PhutilSafeHTML' => 'infrastructure/markup/PhutilSafeHTML.php', | ||||||
|  |     'PhutilSafeHTMLProducerInterface' => 'infrastructure/markup/PhutilSafeHTMLProducerInterface.php', | ||||||
|  |     'PhutilSafeHTMLTestCase' => 'infrastructure/markup/__tests__/PhutilSafeHTMLTestCase.php', | ||||||
|     'PhutilSearchQueryCompiler' => 'applications/search/compiler/PhutilSearchQueryCompiler.php', |     'PhutilSearchQueryCompiler' => 'applications/search/compiler/PhutilSearchQueryCompiler.php', | ||||||
|     'PhutilSearchQueryCompilerSyntaxException' => 'applications/search/compiler/PhutilSearchQueryCompilerSyntaxException.php', |     'PhutilSearchQueryCompilerSyntaxException' => 'applications/search/compiler/PhutilSearchQueryCompilerSyntaxException.php', | ||||||
|     'PhutilSearchQueryCompilerTestCase' => 'applications/search/compiler/__tests__/PhutilSearchQueryCompilerTestCase.php', |     'PhutilSearchQueryCompilerTestCase' => 'applications/search/compiler/__tests__/PhutilSearchQueryCompilerTestCase.php', | ||||||
| @@ -5674,9 +5757,18 @@ phutil_register_library_map(array( | |||||||
|     'PhutilSearchStemmer' => 'applications/search/compiler/PhutilSearchStemmer.php', |     'PhutilSearchStemmer' => 'applications/search/compiler/PhutilSearchStemmer.php', | ||||||
|     'PhutilSearchStemmerTestCase' => 'applications/search/compiler/__tests__/PhutilSearchStemmerTestCase.php', |     'PhutilSearchStemmerTestCase' => 'applications/search/compiler/__tests__/PhutilSearchStemmerTestCase.php', | ||||||
|     'PhutilSlackAuthAdapter' => 'applications/auth/adapter/PhutilSlackAuthAdapter.php', |     'PhutilSlackAuthAdapter' => 'applications/auth/adapter/PhutilSlackAuthAdapter.php', | ||||||
|  |     'PhutilSprite' => 'aphront/sprite/PhutilSprite.php', | ||||||
|  |     'PhutilSpriteSheet' => 'aphront/sprite/PhutilSpriteSheet.php', | ||||||
|  |     'PhutilSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilSyntaxHighlighter.php', | ||||||
|  |     'PhutilSyntaxHighlighterEngine' => 'infrastructure/markup/syntax/engine/PhutilSyntaxHighlighterEngine.php', | ||||||
|  |     'PhutilSyntaxHighlighterException' => 'infrastructure/markup/syntax/highlighter/PhutilSyntaxHighlighterException.php', | ||||||
|  |     'PhutilTranslatedHTMLTestCase' => 'infrastructure/markup/__tests__/PhutilTranslatedHTMLTestCase.php', | ||||||
|     'PhutilTwitchAuthAdapter' => 'applications/auth/adapter/PhutilTwitchAuthAdapter.php', |     'PhutilTwitchAuthAdapter' => 'applications/auth/adapter/PhutilTwitchAuthAdapter.php', | ||||||
|     'PhutilTwitterAuthAdapter' => 'applications/auth/adapter/PhutilTwitterAuthAdapter.php', |     'PhutilTwitterAuthAdapter' => 'applications/auth/adapter/PhutilTwitterAuthAdapter.php', | ||||||
|     'PhutilWordPressAuthAdapter' => 'applications/auth/adapter/PhutilWordPressAuthAdapter.php', |     'PhutilWordPressAuthAdapter' => 'applications/auth/adapter/PhutilWordPressAuthAdapter.php', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighter' => 'infrastructure/markup/syntax/highlighter/PhutilXHPASTSyntaxHighlighter.php', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighterFuture' => 'infrastructure/markup/syntax/highlighter/xhpast/PhutilXHPASTSyntaxHighlighterFuture.php', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighterTestCase' => 'infrastructure/markup/syntax/highlighter/__tests__/PhutilXHPASTSyntaxHighlighterTestCase.php', | ||||||
|     'PolicyLockOptionType' => 'applications/policy/config/PolicyLockOptionType.php', |     'PolicyLockOptionType' => 'applications/policy/config/PolicyLockOptionType.php', | ||||||
|     'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', |     'PonderAddAnswerView' => 'applications/ponder/view/PonderAddAnswerView.php', | ||||||
|     'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', |     'PonderAnswer' => 'applications/ponder/storage/PonderAnswer.php', | ||||||
| @@ -5868,6 +5960,7 @@ phutil_register_library_map(array( | |||||||
|   'function' => array( |   'function' => array( | ||||||
|     'celerity_generate_unique_node_id' => 'applications/celerity/api.php', |     'celerity_generate_unique_node_id' => 'applications/celerity/api.php', | ||||||
|     'celerity_get_resource_uri' => 'applications/celerity/api.php', |     'celerity_get_resource_uri' => 'applications/celerity/api.php', | ||||||
|  |     'hsprintf' => 'infrastructure/markup/render.php', | ||||||
|     'javelin_tag' => 'infrastructure/javelin/markup.php', |     'javelin_tag' => 'infrastructure/javelin/markup.php', | ||||||
|     'phabricator_date' => 'view/viewutils.php', |     'phabricator_date' => 'view/viewutils.php', | ||||||
|     'phabricator_datetime' => 'view/viewutils.php', |     'phabricator_datetime' => 'view/viewutils.php', | ||||||
| @@ -5879,6 +5972,12 @@ phutil_register_library_map(array( | |||||||
|     'phid_get_subtype' => 'applications/phid/utils.php', |     'phid_get_subtype' => 'applications/phid/utils.php', | ||||||
|     'phid_get_type' => 'applications/phid/utils.php', |     'phid_get_type' => 'applications/phid/utils.php', | ||||||
|     'phid_group_by_type' => 'applications/phid/utils.php', |     'phid_group_by_type' => 'applications/phid/utils.php', | ||||||
|  |     'phutil_escape_html' => 'infrastructure/markup/render.php', | ||||||
|  |     'phutil_escape_html_newlines' => 'infrastructure/markup/render.php', | ||||||
|  |     'phutil_implode_html' => 'infrastructure/markup/render.php', | ||||||
|  |     'phutil_safe_html' => 'infrastructure/markup/render.php', | ||||||
|  |     'phutil_tag' => 'infrastructure/markup/render.php', | ||||||
|  |     'phutil_tag_div' => 'infrastructure/markup/render.php', | ||||||
|     'qsprintf' => 'infrastructure/storage/xsprintf/qsprintf.php', |     'qsprintf' => 'infrastructure/storage/xsprintf/qsprintf.php', | ||||||
|     'qsprintf_check_scalar_type' => 'infrastructure/storage/xsprintf/qsprintf.php', |     'qsprintf_check_scalar_type' => 'infrastructure/storage/xsprintf/qsprintf.php', | ||||||
|     'qsprintf_check_type' => 'infrastructure/storage/xsprintf/qsprintf.php', |     'qsprintf_check_type' => 'infrastructure/storage/xsprintf/qsprintf.php', | ||||||
| @@ -6114,6 +6213,7 @@ phutil_register_library_map(array( | |||||||
|     'AphrontAccessDeniedQueryException' => 'AphrontQueryException', |     'AphrontAccessDeniedQueryException' => 'AphrontQueryException', | ||||||
|     'AphrontAjaxResponse' => 'AphrontResponse', |     'AphrontAjaxResponse' => 'AphrontResponse', | ||||||
|     'AphrontApplicationConfiguration' => 'Phobject', |     'AphrontApplicationConfiguration' => 'Phobject', | ||||||
|  |     'AphrontAutoIDView' => 'AphrontView', | ||||||
|     'AphrontBarView' => 'AphrontView', |     'AphrontBarView' => 'AphrontView', | ||||||
|     'AphrontBaseMySQLDatabaseConnection' => 'AphrontDatabaseConnection', |     'AphrontBaseMySQLDatabaseConnection' => 'AphrontDatabaseConnection', | ||||||
|     'AphrontBoolHTTPParameterType' => 'AphrontHTTPParameterType', |     'AphrontBoolHTTPParameterType' => 'AphrontHTTPParameterType', | ||||||
| @@ -6167,6 +6267,8 @@ phutil_register_library_map(array( | |||||||
|     'AphrontFormView' => 'AphrontView', |     'AphrontFormView' => 'AphrontView', | ||||||
|     'AphrontGlyphBarView' => 'AphrontBarView', |     'AphrontGlyphBarView' => 'AphrontBarView', | ||||||
|     'AphrontHTMLResponse' => 'AphrontResponse', |     'AphrontHTMLResponse' => 'AphrontResponse', | ||||||
|  |     'AphrontHTTPHeaderParser' => 'Phobject', | ||||||
|  |     'AphrontHTTPHeaderParserTestCase' => 'PhutilTestCase', | ||||||
|     'AphrontHTTPParameterType' => 'Phobject', |     'AphrontHTTPParameterType' => 'Phobject', | ||||||
|     'AphrontHTTPProxyResponse' => 'AphrontResponse', |     'AphrontHTTPProxyResponse' => 'AphrontResponse', | ||||||
|     'AphrontHTTPSink' => 'Phobject', |     'AphrontHTTPSink' => 'Phobject', | ||||||
| @@ -6185,6 +6287,9 @@ phutil_register_library_map(array( | |||||||
|     'AphrontMalformedRequestException' => 'AphrontException', |     'AphrontMalformedRequestException' => 'AphrontException', | ||||||
|     'AphrontMoreView' => 'AphrontView', |     'AphrontMoreView' => 'AphrontView', | ||||||
|     'AphrontMultiColumnView' => 'AphrontView', |     'AphrontMultiColumnView' => 'AphrontView', | ||||||
|  |     'AphrontMultipartParser' => 'Phobject', | ||||||
|  |     'AphrontMultipartParserTestCase' => 'PhutilTestCase', | ||||||
|  |     'AphrontMultipartPart' => 'Phobject', | ||||||
|     'AphrontMySQLDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', |     'AphrontMySQLDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', | ||||||
|     'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', |     'AphrontMySQLDatabaseConnectionTestCase' => 'PhabricatorTestCase', | ||||||
|     'AphrontMySQLiDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', |     'AphrontMySQLiDatabaseConnection' => 'AphrontBaseMySQLDatabaseConnection', | ||||||
| @@ -6211,11 +6316,14 @@ phutil_register_library_map(array( | |||||||
|     'AphrontReloadResponse' => 'AphrontRedirectResponse', |     'AphrontReloadResponse' => 'AphrontRedirectResponse', | ||||||
|     'AphrontRequest' => 'Phobject', |     'AphrontRequest' => 'Phobject', | ||||||
|     'AphrontRequestExceptionHandler' => 'Phobject', |     'AphrontRequestExceptionHandler' => 'Phobject', | ||||||
|  |     'AphrontRequestStream' => 'Phobject', | ||||||
|     'AphrontRequestTestCase' => 'PhabricatorTestCase', |     'AphrontRequestTestCase' => 'PhabricatorTestCase', | ||||||
|     'AphrontResponse' => 'Phobject', |     'AphrontResponse' => 'Phobject', | ||||||
|     'AphrontRoutingMap' => 'Phobject', |     'AphrontRoutingMap' => 'Phobject', | ||||||
|  |     'AphrontRoutingMapTestCase' => 'PhabricatorTestCase', | ||||||
|     'AphrontRoutingResult' => 'Phobject', |     'AphrontRoutingResult' => 'Phobject', | ||||||
|     'AphrontSchemaQueryException' => 'AphrontQueryException', |     'AphrontSchemaQueryException' => 'AphrontQueryException', | ||||||
|  |     'AphrontScopedUnguardedWriteCapability' => 'Phobject', | ||||||
|     'AphrontSelectHTTPParameterType' => 'AphrontHTTPParameterType', |     'AphrontSelectHTTPParameterType' => 'AphrontHTTPParameterType', | ||||||
|     'AphrontSideNavFilterView' => 'AphrontView', |     'AphrontSideNavFilterView' => 'AphrontView', | ||||||
|     'AphrontSite' => 'Phobject', |     'AphrontSite' => 'Phobject', | ||||||
| @@ -6234,6 +6342,7 @@ phutil_register_library_map(array( | |||||||
|       'PhutilSafeHTMLProducerInterface', |       'PhutilSafeHTMLProducerInterface', | ||||||
|     ), |     ), | ||||||
|     'AphrontWebpageResponse' => 'AphrontHTMLResponse', |     'AphrontWebpageResponse' => 'AphrontHTMLResponse', | ||||||
|  |     'AphrontWriteGuard' => 'Phobject', | ||||||
|     'ArcanistConduitAPIMethod' => 'ConduitAPIMethod', |     'ArcanistConduitAPIMethod' => 'ConduitAPIMethod', | ||||||
|     'AuditConduitAPIMethod' => 'ConduitAPIMethod', |     'AuditConduitAPIMethod' => 'ConduitAPIMethod', | ||||||
|     'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod', |     'AuditQueryConduitAPIMethod' => 'AuditConduitAPIMethod', | ||||||
| @@ -6418,7 +6527,6 @@ phutil_register_library_map(array( | |||||||
|     ), |     ), | ||||||
|     'DifferentialChangesetDetailView' => 'AphrontView', |     'DifferentialChangesetDetailView' => 'AphrontView', | ||||||
|     'DifferentialChangesetEngine' => 'Phobject', |     'DifferentialChangesetEngine' => 'Phobject', | ||||||
|     'DifferentialChangesetFileTreeSideNavBuilder' => 'Phobject', |  | ||||||
|     'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', |     'DifferentialChangesetHTMLRenderer' => 'DifferentialChangesetRenderer', | ||||||
|     'DifferentialChangesetListController' => 'DifferentialController', |     'DifferentialChangesetListController' => 'DifferentialController', | ||||||
|     'DifferentialChangesetListView' => 'AphrontView', |     'DifferentialChangesetListView' => 'AphrontView', | ||||||
| @@ -6501,6 +6609,7 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', |     'DifferentialExactUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', | ||||||
|     'DifferentialFieldParseException' => 'Exception', |     'DifferentialFieldParseException' => 'Exception', | ||||||
|     'DifferentialFieldValidationException' => 'Exception', |     'DifferentialFieldValidationException' => 'Exception', | ||||||
|  |     'DifferentialFileTreeEngine' => 'Phobject', | ||||||
|     'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', |     'DifferentialGetAllDiffsConduitAPIMethod' => 'DifferentialConduitAPIMethod', | ||||||
|     'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', |     'DifferentialGetCommitMessageConduitAPIMethod' => 'DifferentialConduitAPIMethod', | ||||||
|     'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod', |     'DifferentialGetCommitPathsConduitAPIMethod' => 'DifferentialConduitAPIMethod', | ||||||
| @@ -6524,13 +6633,9 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialHunkParserTestCase' => 'PhabricatorTestCase', |     'DifferentialHunkParserTestCase' => 'PhabricatorTestCase', | ||||||
|     'DifferentialHunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'DifferentialHunkQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'DifferentialHunkTestCase' => 'PhutilTestCase', |     'DifferentialHunkTestCase' => 'PhutilTestCase', | ||||||
|     'DifferentialInlineComment' => array( |     'DifferentialInlineComment' => 'PhabricatorInlineComment', | ||||||
|       'Phobject', |  | ||||||
|       'PhabricatorInlineCommentInterface', |  | ||||||
|     ), |  | ||||||
|     'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController', |     'DifferentialInlineCommentEditController' => 'PhabricatorInlineCommentController', | ||||||
|     'DifferentialInlineCommentMailView' => 'DifferentialMailView', |     'DifferentialInlineCommentMailView' => 'DifferentialMailView', | ||||||
|     'DifferentialInlineCommentQuery' => 'PhabricatorOffsetPagedQuery', |  | ||||||
|     'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', |     'DifferentialJIRAIssuesCommitMessageField' => 'DifferentialCommitMessageCustomField', | ||||||
|     'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', |     'DifferentialJIRAIssuesField' => 'DifferentialStoredCustomField', | ||||||
|     'DifferentialLegacyQuery' => 'Phobject', |     'DifferentialLegacyQuery' => 'Phobject', | ||||||
| @@ -6694,7 +6799,10 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialTestPlanField' => 'DifferentialCoreCustomField', |     'DifferentialTestPlanField' => 'DifferentialCoreCustomField', | ||||||
|     'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', |     'DifferentialTitleCommitMessageField' => 'DifferentialCommitMessageField', | ||||||
|     'DifferentialTransaction' => 'PhabricatorModularTransaction', |     'DifferentialTransaction' => 'PhabricatorModularTransaction', | ||||||
|     'DifferentialTransactionComment' => 'PhabricatorApplicationTransactionComment', |     'DifferentialTransactionComment' => array( | ||||||
|  |       'PhabricatorApplicationTransactionComment', | ||||||
|  |       'PhabricatorInlineCommentInterface', | ||||||
|  |     ), | ||||||
|     'DifferentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', |     'DifferentialTransactionEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
|     'DifferentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', |     'DifferentialTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||||
|     'DifferentialTransactionView' => 'PhabricatorApplicationTransactionView', |     'DifferentialTransactionView' => 'PhabricatorApplicationTransactionView', | ||||||
| @@ -6702,6 +6810,12 @@ phutil_register_library_map(array( | |||||||
|     'DifferentialUnitStatus' => 'Phobject', |     'DifferentialUnitStatus' => 'Phobject', | ||||||
|     'DifferentialUnitTestResult' => 'Phobject', |     'DifferentialUnitTestResult' => 'Phobject', | ||||||
|     'DifferentialUpdateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', |     'DifferentialUpdateRevisionConduitAPIMethod' => 'DifferentialConduitAPIMethod', | ||||||
|  |     'DifferentialViewState' => array( | ||||||
|  |       'DifferentialDAO', | ||||||
|  |       'PhabricatorPolicyInterface', | ||||||
|  |     ), | ||||||
|  |     'DifferentialViewStateGarbageCollector' => 'PhabricatorGarbageCollector', | ||||||
|  |     'DifferentialViewStateQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', |     'DiffusionAuditorDatasource' => 'PhabricatorTypeaheadCompositeDatasource', | ||||||
|     'DiffusionAuditorFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', |     'DiffusionAuditorFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource', | ||||||
|     'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', |     'DiffusionAuditorsAddAuditorsHeraldAction' => 'DiffusionAuditorsHeraldAction', | ||||||
| @@ -6865,7 +6979,6 @@ phutil_register_library_map(array( | |||||||
|     'DiffusionIdentityUnassignedDatasource' => 'PhabricatorTypeaheadDatasource', |     'DiffusionIdentityUnassignedDatasource' => 'PhabricatorTypeaheadDatasource', | ||||||
|     'DiffusionIdentityViewController' => 'DiffusionController', |     'DiffusionIdentityViewController' => 'DiffusionController', | ||||||
|     'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', |     'DiffusionInlineCommentController' => 'PhabricatorInlineCommentController', | ||||||
|     'DiffusionInlineCommentPreviewController' => 'PhabricatorInlineCommentPreviewController', |  | ||||||
|     'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', |     'DiffusionInternalAncestorsConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', | ||||||
|     'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', |     'DiffusionInternalGitRawDiffQueryConduitAPIMethod' => 'DiffusionQueryConduitAPIMethod', | ||||||
|     'DiffusionLastModifiedController' => 'DiffusionController', |     'DiffusionLastModifiedController' => 'DiffusionController', | ||||||
| @@ -7325,6 +7438,8 @@ phutil_register_library_map(array( | |||||||
|     'FeedPushWorker' => 'PhabricatorWorker', |     'FeedPushWorker' => 'PhabricatorWorker', | ||||||
|     'FeedQueryConduitAPIMethod' => 'FeedConduitAPIMethod', |     'FeedQueryConduitAPIMethod' => 'FeedConduitAPIMethod', | ||||||
|     'FeedStoryNotificationGarbageCollector' => 'PhabricatorGarbageCollector', |     'FeedStoryNotificationGarbageCollector' => 'PhabricatorGarbageCollector', | ||||||
|  |     'FerretConfigurableSearchFunction' => 'FerretSearchFunction', | ||||||
|  |     'FerretSearchFunction' => 'Phobject', | ||||||
|     'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod', |     'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod', | ||||||
|     'FileConduitAPIMethod' => 'ConduitAPIMethod', |     'FileConduitAPIMethod' => 'ConduitAPIMethod', | ||||||
|     'FileCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', |     'FileCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', | ||||||
| @@ -7916,6 +8031,7 @@ phutil_register_library_map(array( | |||||||
|     'ManiphestReportController' => 'ManiphestController', |     'ManiphestReportController' => 'ManiphestController', | ||||||
|     'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', |     'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec', | ||||||
|     'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', |     'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', | ||||||
|  |     'ManiphestSearchController' => 'PhabricatorApplicationSearchController', | ||||||
|     'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand', |     'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand', | ||||||
|     'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', |     'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod', | ||||||
|     'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType', |     'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType', | ||||||
| @@ -8189,6 +8305,8 @@ phutil_register_library_map(array( | |||||||
|     'PHUICrumbView' => 'AphrontView', |     'PHUICrumbView' => 'AphrontView', | ||||||
|     'PHUICrumbsView' => 'AphrontView', |     'PHUICrumbsView' => 'AphrontView', | ||||||
|     'PHUICurtainExtension' => 'Phobject', |     'PHUICurtainExtension' => 'Phobject', | ||||||
|  |     'PHUICurtainObjectRefListView' => 'AphrontTagView', | ||||||
|  |     'PHUICurtainObjectRefView' => 'AphrontTagView', | ||||||
|     'PHUICurtainPanelView' => 'AphrontTagView', |     'PHUICurtainPanelView' => 'AphrontTagView', | ||||||
|     'PHUICurtainView' => 'AphrontTagView', |     'PHUICurtainView' => 'AphrontTagView', | ||||||
|     'PHUIDiffGraphView' => 'Phobject', |     'PHUIDiffGraphView' => 'Phobject', | ||||||
| @@ -8218,6 +8336,14 @@ phutil_register_library_map(array( | |||||||
|     'PHUIFormLayoutView' => 'AphrontView', |     'PHUIFormLayoutView' => 'AphrontView', | ||||||
|     'PHUIFormNumberControl' => 'AphrontFormControl', |     'PHUIFormNumberControl' => 'AphrontFormControl', | ||||||
|     'PHUIFormTimerControl' => 'AphrontFormControl', |     'PHUIFormTimerControl' => 'AphrontFormControl', | ||||||
|  |     'PHUIFormationColumnDynamicView' => 'PHUIFormationColumnView', | ||||||
|  |     'PHUIFormationColumnItem' => 'Phobject', | ||||||
|  |     'PHUIFormationColumnView' => 'AphrontAutoIDView', | ||||||
|  |     'PHUIFormationContentView' => 'PHUIFormationColumnView', | ||||||
|  |     'PHUIFormationExpanderView' => 'AphrontAutoIDView', | ||||||
|  |     'PHUIFormationFlankView' => 'PHUIFormationColumnDynamicView', | ||||||
|  |     'PHUIFormationResizerView' => 'PHUIFormationColumnView', | ||||||
|  |     'PHUIFormationView' => 'AphrontAutoIDView', | ||||||
|     'PHUIHandleListView' => 'AphrontTagView', |     'PHUIHandleListView' => 'AphrontTagView', | ||||||
|     'PHUIHandleTagListView' => 'AphrontTagView', |     'PHUIHandleTagListView' => 'AphrontTagView', | ||||||
|     'PHUIHandleView' => 'AphrontView', |     'PHUIHandleView' => 'AphrontView', | ||||||
| @@ -8235,8 +8361,10 @@ phutil_register_library_map(array( | |||||||
|     'PHUIInfoView' => 'AphrontTagView', |     'PHUIInfoView' => 'AphrontTagView', | ||||||
|     'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', |     'PHUIInvisibleCharacterTestCase' => 'PhabricatorTestCase', | ||||||
|     'PHUIInvisibleCharacterView' => 'AphrontView', |     'PHUIInvisibleCharacterView' => 'AphrontView', | ||||||
|  |     'PHUILauncherView' => 'AphrontTagView', | ||||||
|     'PHUILeftRightExample' => 'PhabricatorUIExample', |     'PHUILeftRightExample' => 'PhabricatorUIExample', | ||||||
|     'PHUILeftRightView' => 'AphrontTagView', |     'PHUILeftRightView' => 'AphrontTagView', | ||||||
|  |     'PHUILinkView' => 'AphrontTagView', | ||||||
|     'PHUIListExample' => 'PhabricatorUIExample', |     'PHUIListExample' => 'PhabricatorUIExample', | ||||||
|     'PHUIListItemView' => 'AphrontTagView', |     'PHUIListItemView' => 'AphrontTagView', | ||||||
|     'PHUIListView' => 'AphrontTagView', |     'PHUIListView' => 'AphrontTagView', | ||||||
| @@ -8348,6 +8476,7 @@ phutil_register_library_map(array( | |||||||
|     'PasteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', |     'PasteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', | ||||||
|     'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', |     'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability', | ||||||
|     'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', |     'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability', | ||||||
|  |     'PeopleDisableSpamUsersCapability' => 'PhabricatorPolicyCapability', | ||||||
|     'PeopleDisableUsersCapability' => 'PhabricatorPolicyCapability', |     'PeopleDisableUsersCapability' => 'PhabricatorPolicyCapability', | ||||||
|     'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', |     'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension', | ||||||
|     'PeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', |     'PeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension', | ||||||
| @@ -8417,6 +8546,7 @@ phutil_register_library_map(array( | |||||||
|       'PhabricatorPolicyInterface', |       'PhabricatorPolicyInterface', | ||||||
|       'PhabricatorDestructibleInterface', |       'PhabricatorDestructibleInterface', | ||||||
|     ), |     ), | ||||||
|  |     'PhabricatorApplicationTransactionCannedResponsesController' => 'PhabricatorApplicationTransactionController', | ||||||
|     'PhabricatorApplicationTransactionComment' => array( |     'PhabricatorApplicationTransactionComment' => array( | ||||||
|       'PhabricatorLiskDAO', |       'PhabricatorLiskDAO', | ||||||
|       'PhabricatorMarkupInterface', |       'PhabricatorMarkupInterface', | ||||||
| @@ -8476,10 +8606,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', |     'PhabricatorAuditCommentEditor' => 'PhabricatorEditor', | ||||||
|     'PhabricatorAuditController' => 'PhabricatorController', |     'PhabricatorAuditController' => 'PhabricatorController', | ||||||
|     'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor', |     'PhabricatorAuditEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
|     'PhabricatorAuditInlineComment' => array( |     'PhabricatorAuditInlineComment' => 'PhabricatorInlineComment', | ||||||
|       'Phobject', |  | ||||||
|       'PhabricatorInlineCommentInterface', |  | ||||||
|     ), |  | ||||||
|     'PhabricatorAuditListView' => 'AphrontView', |     'PhabricatorAuditListView' => 'AphrontView', | ||||||
|     'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver', |     'PhabricatorAuditMailReceiver' => 'PhabricatorObjectMailReceiver', | ||||||
|     'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow', |     'PhabricatorAuditManagementDeleteWorkflow' => 'PhabricatorAuditManagementWorkflow', | ||||||
| @@ -8488,7 +8615,10 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorAuditStatusConstants' => 'Phobject', |     'PhabricatorAuditStatusConstants' => 'Phobject', | ||||||
|     'PhabricatorAuditSynchronizeManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', |     'PhabricatorAuditSynchronizeManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', | ||||||
|     'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction', |     'PhabricatorAuditTransaction' => 'PhabricatorModularTransaction', | ||||||
|     'PhabricatorAuditTransactionComment' => 'PhabricatorApplicationTransactionComment', |     'PhabricatorAuditTransactionComment' => array( | ||||||
|  |       'PhabricatorApplicationTransactionComment', | ||||||
|  |       'PhabricatorInlineCommentInterface', | ||||||
|  |     ), | ||||||
|     'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery', |     'PhabricatorAuditTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||||
|     'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView', |     'PhabricatorAuditTransactionView' => 'PhabricatorApplicationTransactionView', | ||||||
|     'PhabricatorAuditUpdateOwnersManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', |     'PhabricatorAuditUpdateOwnersManagementWorkflow' => 'PhabricatorAuditManagementWorkflow', | ||||||
| @@ -8678,6 +8808,7 @@ phutil_register_library_map(array( | |||||||
|       'PhabricatorAuthDAO', |       'PhabricatorAuthDAO', | ||||||
|       'PhabricatorApplicationTransactionInterface', |       'PhabricatorApplicationTransactionInterface', | ||||||
|       'PhabricatorPolicyInterface', |       'PhabricatorPolicyInterface', | ||||||
|  |       'PhabricatorDestructibleInterface', | ||||||
|     ), |     ), | ||||||
|     'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthProviderController', |     'PhabricatorAuthProviderConfigController' => 'PhabricatorAuthProviderController', | ||||||
|     'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', |     'PhabricatorAuthProviderConfigEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
| @@ -9042,6 +9173,8 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorChangePasswordUserLogType' => 'PhabricatorUserLogType', |     'PhabricatorChangePasswordUserLogType' => 'PhabricatorUserLogType', | ||||||
|     'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger', |     'PhabricatorChangesetCachePurger' => 'PhabricatorCachePurger', | ||||||
|     'PhabricatorChangesetResponse' => 'AphrontProxyResponse', |     'PhabricatorChangesetResponse' => 'AphrontProxyResponse', | ||||||
|  |     'PhabricatorChangesetViewState' => 'Phobject', | ||||||
|  |     'PhabricatorChangesetViewStateEngine' => 'Phobject', | ||||||
|     'PhabricatorChartAxis' => 'Phobject', |     'PhabricatorChartAxis' => 'Phobject', | ||||||
|     'PhabricatorChartDataQuery' => 'Phobject', |     'PhabricatorChartDataQuery' => 'Phobject', | ||||||
|     'PhabricatorChartDataset' => 'Phobject', |     'PhabricatorChartDataset' => 'Phobject', | ||||||
| @@ -9131,21 +9264,20 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConduitTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'PhabricatorConduitTokenQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhabricatorConduitTokenTerminateController' => 'PhabricatorConduitController', |     'PhabricatorConduitTokenTerminateController' => 'PhabricatorConduitController', | ||||||
|     'PhabricatorConduitTokensSettingsPanel' => 'PhabricatorSettingsPanel', |     'PhabricatorConduitTokensSettingsPanel' => 'PhabricatorSettingsPanel', | ||||||
|     'PhabricatorConfigAllController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConfigApplication' => 'PhabricatorApplication', |     'PhabricatorConfigApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorConfigApplicationController' => 'PhabricatorConfigController', |     'PhabricatorConfigCacheController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigCacheController' => 'PhabricatorConfigController', |     'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigClusterDatabasesController' => 'PhabricatorConfigController', |     'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigClusterNotificationsController' => 'PhabricatorConfigController', |     'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigClusterRepositoriesController' => 'PhabricatorConfigController', |     'PhabricatorConfigClusterSearchController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigClusterSearchController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConfigCollectorsModule' => 'PhabricatorConfigModule', |     'PhabricatorConfigCollectorsModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema', |     'PhabricatorConfigColumnSchema' => 'PhabricatorConfigStorageSchema', | ||||||
|     'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType', |     'PhabricatorConfigConfigPHIDType' => 'PhabricatorPHIDType', | ||||||
|  |     'PhabricatorConfigConsoleController' => 'PhabricatorConfigController', | ||||||
|     'PhabricatorConfigConstants' => 'Phobject', |     'PhabricatorConfigConstants' => 'Phobject', | ||||||
|     'PhabricatorConfigController' => 'PhabricatorController', |     'PhabricatorConfigController' => 'PhabricatorController', | ||||||
|     'PhabricatorConfigCoreSchemaSpec' => 'PhabricatorConfigSchemaSpec', |     'PhabricatorConfigCoreSchemaSpec' => 'PhabricatorConfigSchemaSpec', | ||||||
|     'PhabricatorConfigDatabaseController' => 'PhabricatorConfigController', |     'PhabricatorConfigDatabaseController' => 'PhabricatorConfigServicesController', | ||||||
|     'PhabricatorConfigDatabaseIssueController' => 'PhabricatorConfigDatabaseController', |     'PhabricatorConfigDatabaseIssueController' => 'PhabricatorConfigDatabaseController', | ||||||
|     'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema', |     'PhabricatorConfigDatabaseSchema' => 'PhabricatorConfigStorageSchema', | ||||||
|     'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource', |     'PhabricatorConfigDatabaseSource' => 'PhabricatorConfigProxySource', | ||||||
| @@ -9153,7 +9285,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource', |     'PhabricatorConfigDefaultSource' => 'PhabricatorConfigProxySource', | ||||||
|     'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource', |     'PhabricatorConfigDictionarySource' => 'PhabricatorConfigSource', | ||||||
|     'PhabricatorConfigEdgeModule' => 'PhabricatorConfigModule', |     'PhabricatorConfigEdgeModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorConfigEditController' => 'PhabricatorConfigController', |     'PhabricatorConfigEditController' => 'PhabricatorConfigSettingsController', | ||||||
|     'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor', |     'PhabricatorConfigEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
|     'PhabricatorConfigEntry' => array( |     'PhabricatorConfigEntry' => array( | ||||||
|       'PhabricatorConfigEntryDAO', |       'PhabricatorConfigEntryDAO', | ||||||
| @@ -9164,9 +9296,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'PhabricatorConfigEntryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', |     'PhabricatorConfigFileSource' => 'PhabricatorConfigProxySource', | ||||||
|     'PhabricatorConfigGroupConstants' => 'PhabricatorConfigConstants', |     'PhabricatorConfigGroupConstants' => 'PhabricatorConfigConstants', | ||||||
|     'PhabricatorConfigGroupController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConfigHTTPParameterTypesModule' => 'PhabricatorConfigModule', |     'PhabricatorConfigHTTPParameterTypesModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorConfigHistoryController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConfigIgnoreController' => 'PhabricatorConfigController', |     'PhabricatorConfigIgnoreController' => 'PhabricatorConfigController', | ||||||
|     'PhabricatorConfigIssueListController' => 'PhabricatorConfigController', |     'PhabricatorConfigIssueListController' => 'PhabricatorConfigController', | ||||||
|     'PhabricatorConfigIssuePanelController' => 'PhabricatorConfigController', |     'PhabricatorConfigIssuePanelController' => 'PhabricatorConfigController', | ||||||
| @@ -9174,7 +9304,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigJSON' => 'Phobject', |     'PhabricatorConfigJSON' => 'Phobject', | ||||||
|     'PhabricatorConfigJSONOptionType' => 'PhabricatorConfigOptionType', |     'PhabricatorConfigJSONOptionType' => 'PhabricatorConfigOptionType', | ||||||
|     'PhabricatorConfigKeySchema' => 'PhabricatorConfigStorageSchema', |     'PhabricatorConfigKeySchema' => 'PhabricatorConfigStorageSchema', | ||||||
|     'PhabricatorConfigListController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', |     'PhabricatorConfigLocalSource' => 'PhabricatorConfigProxySource', | ||||||
|     'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', |     'PhabricatorConfigManagementDeleteWorkflow' => 'PhabricatorConfigManagementWorkflow', | ||||||
|     'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow', |     'PhabricatorConfigManagementDoneWorkflow' => 'PhabricatorConfigManagementWorkflow', | ||||||
| @@ -9198,6 +9327,10 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigSchemaQuery' => 'Phobject', |     'PhabricatorConfigSchemaQuery' => 'Phobject', | ||||||
|     'PhabricatorConfigSchemaSpec' => 'Phobject', |     'PhabricatorConfigSchemaSpec' => 'Phobject', | ||||||
|     'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema', |     'PhabricatorConfigServerSchema' => 'PhabricatorConfigStorageSchema', | ||||||
|  |     'PhabricatorConfigServicesController' => 'PhabricatorConfigController', | ||||||
|  |     'PhabricatorConfigSettingsController' => 'PhabricatorConfigController', | ||||||
|  |     'PhabricatorConfigSettingsHistoryController' => 'PhabricatorConfigSettingsController', | ||||||
|  |     'PhabricatorConfigSettingsListController' => 'PhabricatorConfigSettingsController', | ||||||
|     'PhabricatorConfigSetupCheckModule' => 'PhabricatorConfigModule', |     'PhabricatorConfigSetupCheckModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorConfigSiteModule' => 'PhabricatorConfigModule', |     'PhabricatorConfigSiteModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource', |     'PhabricatorConfigSiteSource' => 'PhabricatorConfigProxySource', | ||||||
| @@ -9209,7 +9342,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', |     'PhabricatorConfigTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||||
|     'PhabricatorConfigType' => 'Phobject', |     'PhabricatorConfigType' => 'Phobject', | ||||||
|     'PhabricatorConfigValidationException' => 'Exception', |     'PhabricatorConfigValidationException' => 'Exception', | ||||||
|     'PhabricatorConfigVersionController' => 'PhabricatorConfigController', |  | ||||||
|     'PhabricatorConpherenceApplication' => 'PhabricatorApplication', |     'PhabricatorConpherenceApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorConpherenceColumnMinimizeSetting' => 'PhabricatorInternalSetting', |     'PhabricatorConpherenceColumnMinimizeSetting' => 'PhabricatorInternalSetting', | ||||||
|     'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting', |     'PhabricatorConpherenceColumnVisibleSetting' => 'PhabricatorInternalSetting', | ||||||
| @@ -9508,6 +9640,8 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorDestructionEngineExtensionModule' => 'PhabricatorConfigModule', |     'PhabricatorDestructionEngineExtensionModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions', |     'PhabricatorDeveloperConfigOptions' => 'PhabricatorApplicationConfigOptions', | ||||||
|     'PhabricatorDeveloperPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', |     'PhabricatorDeveloperPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', | ||||||
|  |     'PhabricatorDiffInlineCommentContentState' => 'PhabricatorInlineCommentContentState', | ||||||
|  |     'PhabricatorDiffInlineCommentContext' => 'PhabricatorInlineCommentContext', | ||||||
|     'PhabricatorDiffInlineCommentQuery' => 'PhabricatorApplicationTransactionCommentQuery', |     'PhabricatorDiffInlineCommentQuery' => 'PhabricatorApplicationTransactionCommentQuery', | ||||||
|     'PhabricatorDiffPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', |     'PhabricatorDiffPreferencesSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', | ||||||
|     'PhabricatorDiffScopeEngine' => 'Phobject', |     'PhabricatorDiffScopeEngine' => 'Phobject', | ||||||
| @@ -9614,6 +9748,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorEditEngineMFAEngine' => 'Phobject', |     'PhabricatorEditEngineMFAEngine' => 'Phobject', | ||||||
|     'PhabricatorEditEngineNameTransaction' => 'PhabricatorEditEngineTransactionType', |     'PhabricatorEditEngineNameTransaction' => 'PhabricatorEditEngineTransactionType', | ||||||
|     'PhabricatorEditEngineOrderTransaction' => 'PhabricatorEditEngineTransactionType', |     'PhabricatorEditEngineOrderTransaction' => 'PhabricatorEditEngineTransactionType', | ||||||
|  |     'PhabricatorEditEnginePageState' => 'Phobject', | ||||||
|     'PhabricatorEditEnginePointsCommentAction' => 'PhabricatorEditEngineCommentAction', |     'PhabricatorEditEnginePointsCommentAction' => 'PhabricatorEditEngineCommentAction', | ||||||
|     'PhabricatorEditEnginePreambleTransaction' => 'PhabricatorEditEngineTransactionType', |     'PhabricatorEditEnginePreambleTransaction' => 'PhabricatorEditEngineTransactionType', | ||||||
|     'PhabricatorEditEngineProfileMenuItem' => 'PhabricatorProfileMenuItem', |     'PhabricatorEditEngineProfileMenuItem' => 'PhabricatorProfileMenuItem', | ||||||
| @@ -9636,8 +9771,10 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorEditorExtension' => 'Phobject', |     'PhabricatorEditorExtension' => 'Phobject', | ||||||
|     'PhabricatorEditorExtensionModule' => 'PhabricatorConfigModule', |     'PhabricatorEditorExtensionModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorEditorMailEngineExtension' => 'PhabricatorMailEngineExtension', |     'PhabricatorEditorMailEngineExtension' => 'PhabricatorMailEngineExtension', | ||||||
|     'PhabricatorEditorMultipleSetting' => 'PhabricatorSelectSetting', |  | ||||||
|     'PhabricatorEditorSetting' => 'PhabricatorStringSetting', |     'PhabricatorEditorSetting' => 'PhabricatorStringSetting', | ||||||
|  |     'PhabricatorEditorURIEngine' => 'Phobject', | ||||||
|  |     'PhabricatorEditorURIEngineTestCase' => 'PhabricatorTestCase', | ||||||
|  |     'PhabricatorEditorURIParserException' => 'Exception', | ||||||
|     'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', |     'PhabricatorElasticFulltextStorageEngine' => 'PhabricatorFulltextStorageEngine', | ||||||
|     'PhabricatorElasticsearchHost' => 'PhabricatorSearchHost', |     'PhabricatorElasticsearchHost' => 'PhabricatorSearchHost', | ||||||
|     'PhabricatorElasticsearchSetupCheck' => 'PhabricatorSetupCheck', |     'PhabricatorElasticsearchSetupCheck' => 'PhabricatorSetupCheck', | ||||||
| @@ -9686,9 +9823,17 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorExternalAccount' => array( |     'PhabricatorExternalAccount' => array( | ||||||
|       'PhabricatorUserDAO', |       'PhabricatorUserDAO', | ||||||
|       'PhabricatorPolicyInterface', |       'PhabricatorPolicyInterface', | ||||||
|  |       'PhabricatorDestructibleInterface', | ||||||
|     ), |     ), | ||||||
|  |     'PhabricatorExternalAccountIdentifier' => array( | ||||||
|  |       'PhabricatorUserDAO', | ||||||
|  |       'PhabricatorPolicyInterface', | ||||||
|  |       'PhabricatorDestructibleInterface', | ||||||
|  |     ), | ||||||
|  |     'PhabricatorExternalAccountIdentifierQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', |     'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', | ||||||
|     'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel', |     'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel', | ||||||
|  |     'PhabricatorExternalEditorSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', | ||||||
|     'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck', |     'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck', | ||||||
|     'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider', |     'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider', | ||||||
|     'PhabricatorFact' => 'Phobject', |     'PhabricatorFact' => 'Phobject', | ||||||
| @@ -9721,6 +9866,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorFactRaw' => 'PhabricatorFactDAO', |     'PhabricatorFactRaw' => 'PhabricatorFactDAO', | ||||||
|     'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', |     'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator', | ||||||
|     'PhabricatorFailHisecUserLogType' => 'PhabricatorUserLogType', |     'PhabricatorFailHisecUserLogType' => 'PhabricatorUserLogType', | ||||||
|  |     'PhabricatorFaviconController' => 'PhabricatorController', | ||||||
|     'PhabricatorFaviconRef' => 'Phobject', |     'PhabricatorFaviconRef' => 'Phobject', | ||||||
|     'PhabricatorFaviconRefQuery' => 'Phobject', |     'PhabricatorFaviconRefQuery' => 'Phobject', | ||||||
|     'PhabricatorFavoritesApplication' => 'PhabricatorApplication', |     'PhabricatorFavoritesApplication' => 'PhabricatorApplication', | ||||||
| @@ -9949,7 +10095,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorHelpApplication' => 'PhabricatorApplication', |     'PhabricatorHelpApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorHelpController' => 'PhabricatorController', |     'PhabricatorHelpController' => 'PhabricatorController', | ||||||
|     'PhabricatorHelpDocumentationController' => 'PhabricatorHelpController', |     'PhabricatorHelpDocumentationController' => 'PhabricatorHelpController', | ||||||
|     'PhabricatorHelpEditorProtocolController' => 'PhabricatorHelpController', |  | ||||||
|     'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', |     'PhabricatorHelpKeyboardShortcutController' => 'PhabricatorHelpController', | ||||||
|     'PhabricatorHeraldApplication' => 'PhabricatorApplication', |     'PhabricatorHeraldApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorHeraldContentSource' => 'PhabricatorContentSource', |     'PhabricatorHeraldContentSource' => 'PhabricatorContentSource', | ||||||
| @@ -9983,9 +10128,14 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorIndexEngineExtension' => 'Phobject', |     'PhabricatorIndexEngineExtension' => 'Phobject', | ||||||
|     'PhabricatorIndexEngineExtensionModule' => 'PhabricatorConfigModule', |     'PhabricatorIndexEngineExtensionModule' => 'PhabricatorConfigModule', | ||||||
|     'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase', |     'PhabricatorInfrastructureTestCase' => 'PhabricatorTestCase', | ||||||
|  |     'PhabricatorInlineComment' => array( | ||||||
|  |       'Phobject', | ||||||
|  |       'PhabricatorMarkupInterface', | ||||||
|  |     ), | ||||||
|  |     'PhabricatorInlineCommentAdjustmentEngine' => 'Phobject', | ||||||
|  |     'PhabricatorInlineCommentContentState' => 'Phobject', | ||||||
|  |     'PhabricatorInlineCommentContext' => 'Phobject', | ||||||
|     'PhabricatorInlineCommentController' => 'PhabricatorController', |     'PhabricatorInlineCommentController' => 'PhabricatorController', | ||||||
|     'PhabricatorInlineCommentInterface' => 'PhabricatorMarkupInterface', |  | ||||||
|     'PhabricatorInlineCommentPreviewController' => 'PhabricatorController', |  | ||||||
|     'PhabricatorInlineSummaryView' => 'AphrontView', |     'PhabricatorInlineSummaryView' => 'AphrontView', | ||||||
|     'PhabricatorInstructionsEditField' => 'PhabricatorEditField', |     'PhabricatorInstructionsEditField' => 'PhabricatorEditField', | ||||||
|     'PhabricatorIntConfigType' => 'PhabricatorTextConfigType', |     'PhabricatorIntConfigType' => 'PhabricatorTextConfigType', | ||||||
| @@ -10560,6 +10710,8 @@ phutil_register_library_map(array( | |||||||
|       'PhabricatorApplicationTransactionInterface', |       'PhabricatorApplicationTransactionInterface', | ||||||
|       'PhabricatorSpacesInterface', |       'PhabricatorSpacesInterface', | ||||||
|       'PhabricatorConduitResultInterface', |       'PhabricatorConduitResultInterface', | ||||||
|  |       'PhabricatorFerretInterface', | ||||||
|  |       'PhabricatorFulltextInterface', | ||||||
|     ), |     ), | ||||||
|     'PhabricatorPasteApplication' => 'PhabricatorApplication', |     'PhabricatorPasteApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorPasteArchiveController' => 'PhabricatorPasteController', |     'PhabricatorPasteArchiveController' => 'PhabricatorPasteController', | ||||||
| @@ -10570,7 +10722,9 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPasteEditController' => 'PhabricatorPasteController', |     'PhabricatorPasteEditController' => 'PhabricatorPasteController', | ||||||
|     'PhabricatorPasteEditEngine' => 'PhabricatorEditEngine', |     'PhabricatorPasteEditEngine' => 'PhabricatorEditEngine', | ||||||
|     'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor', |     'PhabricatorPasteEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
|  |     'PhabricatorPasteFerretEngine' => 'PhabricatorFerretEngine', | ||||||
|     'PhabricatorPasteFilenameContextFreeGrammar' => 'PhutilContextFreeGrammar', |     'PhabricatorPasteFilenameContextFreeGrammar' => 'PhutilContextFreeGrammar', | ||||||
|  |     'PhabricatorPasteFulltextEngine' => 'PhabricatorFulltextEngine', | ||||||
|     'PhabricatorPasteLanguageTransaction' => 'PhabricatorPasteTransactionType', |     'PhabricatorPasteLanguageTransaction' => 'PhabricatorPasteTransactionType', | ||||||
|     'PhabricatorPasteListController' => 'PhabricatorPasteController', |     'PhabricatorPasteListController' => 'PhabricatorPasteController', | ||||||
|     'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType', |     'PhabricatorPastePastePHIDType' => 'PhabricatorPHIDType', | ||||||
| @@ -10605,6 +10759,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', |     'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController', | ||||||
|     'PhabricatorPeopleEmailLoginMailEngine' => 'PhabricatorPeopleMailEngine', |     'PhabricatorPeopleEmailLoginMailEngine' => 'PhabricatorPeopleMailEngine', | ||||||
|     'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', |     'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController', | ||||||
|  |     'PhabricatorPeopleExternalIdentifierPHIDType' => 'PhabricatorPHIDType', | ||||||
|     'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', |     'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType', | ||||||
|     'PhabricatorPeopleIconSet' => 'PhabricatorIconSet', |     'PhabricatorPeopleIconSet' => 'PhabricatorIconSet', | ||||||
|     'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController', |     'PhabricatorPeopleInviteController' => 'PhabricatorPeopleController', | ||||||
| @@ -10639,6 +10794,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', |     'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController', | ||||||
|     'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem', |     'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem', | ||||||
|     'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', |     'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine', | ||||||
|  |     'PhabricatorPeopleSpamController' => 'PhabricatorPeopleController', | ||||||
|     'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem', |     'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem', | ||||||
|     'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', |     'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator', | ||||||
|     'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery', |     'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||||
| @@ -11329,6 +11485,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSearchManagementNgramsWorkflow' => 'PhabricatorSearchManagementWorkflow', |     'PhabricatorSearchManagementNgramsWorkflow' => 'PhabricatorSearchManagementWorkflow', | ||||||
|     'PhabricatorSearchManagementQueryWorkflow' => 'PhabricatorSearchManagementWorkflow', |     'PhabricatorSearchManagementQueryWorkflow' => 'PhabricatorSearchManagementWorkflow', | ||||||
|     'PhabricatorSearchManagementWorkflow' => 'PhabricatorManagementWorkflow', |     'PhabricatorSearchManagementWorkflow' => 'PhabricatorManagementWorkflow', | ||||||
|  |     'PhabricatorSearchNgramEngine' => 'Phobject', | ||||||
|     'PhabricatorSearchNgrams' => 'PhabricatorSearchDAO', |     'PhabricatorSearchNgrams' => 'PhabricatorSearchDAO', | ||||||
|     'PhabricatorSearchNgramsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', |     'PhabricatorSearchNgramsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', | ||||||
|     'PhabricatorSearchOrderController' => 'PhabricatorSearchBaseController', |     'PhabricatorSearchOrderController' => 'PhabricatorSearchBaseController', | ||||||
| @@ -11372,6 +11529,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup', |     'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup', | ||||||
|     'PhabricatorSettingsMainController' => 'PhabricatorController', |     'PhabricatorSettingsMainController' => 'PhabricatorController', | ||||||
|     'PhabricatorSettingsPanel' => 'Phobject', |     'PhabricatorSettingsPanel' => 'Phobject', | ||||||
|  |     'PhabricatorSettingsPanelChangeUsername' => 'PhabricatorSettingsPanel', | ||||||
|     'PhabricatorSettingsPanelGroup' => 'Phobject', |     'PhabricatorSettingsPanelGroup' => 'Phobject', | ||||||
|     'PhabricatorSettingsTimezoneController' => 'PhabricatorController', |     'PhabricatorSettingsTimezoneController' => 'PhabricatorController', | ||||||
|     'PhabricatorSetupCheck' => 'Phobject', |     'PhabricatorSetupCheck' => 'Phobject', | ||||||
| @@ -11382,7 +11540,6 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorSetupIssueView' => 'AphrontView', |     'PhabricatorSetupIssueView' => 'AphrontView', | ||||||
|     'PhabricatorShiftChartFunction' => 'PhabricatorPureChartFunction', |     'PhabricatorShiftChartFunction' => 'PhabricatorPureChartFunction', | ||||||
|     'PhabricatorShortSite' => 'PhabricatorSite', |     'PhabricatorShortSite' => 'PhabricatorSite', | ||||||
|     'PhabricatorShowFiletreeSetting' => 'PhabricatorSelectSetting', |  | ||||||
|     'PhabricatorSignDocumentsUserLogType' => 'PhabricatorUserLogType', |     'PhabricatorSignDocumentsUserLogType' => 'PhabricatorUserLogType', | ||||||
|     'PhabricatorSimpleEditType' => 'PhabricatorEditType', |     'PhabricatorSimpleEditType' => 'PhabricatorEditType', | ||||||
|     'PhabricatorSinChartFunction' => 'PhabricatorPureChartFunction', |     'PhabricatorSinChartFunction' => 'PhabricatorPureChartFunction', | ||||||
| @@ -11634,6 +11791,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorTransactionChange' => 'Phobject', |     'PhabricatorTransactionChange' => 'Phobject', | ||||||
|     'PhabricatorTransactionFactEngine' => 'PhabricatorFactEngine', |     'PhabricatorTransactionFactEngine' => 'PhabricatorFactEngine', | ||||||
|     'PhabricatorTransactionRemarkupChange' => 'PhabricatorTransactionChange', |     'PhabricatorTransactionRemarkupChange' => 'PhabricatorTransactionChange', | ||||||
|  |     'PhabricatorTransactionWarning' => 'Phobject', | ||||||
|     'PhabricatorTransactions' => 'Phobject', |     'PhabricatorTransactions' => 'Phobject', | ||||||
|     'PhabricatorTransactionsApplication' => 'PhabricatorApplication', |     'PhabricatorTransactionsApplication' => 'PhabricatorApplication', | ||||||
|     'PhabricatorTransactionsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', |     'PhabricatorTransactionsDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension', | ||||||
| @@ -11707,6 +11865,7 @@ phutil_register_library_map(array( | |||||||
|     'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', |     'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage', | ||||||
|     'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', |     'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage', | ||||||
|     'PhabricatorUserDAO' => 'PhabricatorLiskDAO', |     'PhabricatorUserDAO' => 'PhabricatorLiskDAO', | ||||||
|  |     'PhabricatorUserDisableSpamTransaction' => 'PhabricatorUserTransactionType', | ||||||
|     'PhabricatorUserDisableTransaction' => 'PhabricatorUserTransactionType', |     'PhabricatorUserDisableTransaction' => 'PhabricatorUserTransactionType', | ||||||
|     'PhabricatorUserEditEngine' => 'PhabricatorEditEngine', |     'PhabricatorUserEditEngine' => 'PhabricatorEditEngine', | ||||||
|     'PhabricatorUserEditor' => 'PhabricatorEditor', |     'PhabricatorUserEditor' => 'PhabricatorEditor', | ||||||
| @@ -12421,6 +12580,7 @@ phutil_register_library_map(array( | |||||||
|     'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', |     'PhrictionTransactionComment' => 'PhabricatorApplicationTransactionComment', | ||||||
|     'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', |     'PhrictionTransactionEditor' => 'PhabricatorApplicationTransactionEditor', | ||||||
|     'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', |     'PhrictionTransactionQuery' => 'PhabricatorApplicationTransactionQuery', | ||||||
|  |     'PhutilAPCKeyValueCache' => 'PhutilKeyValueCache', | ||||||
|     'PhutilAmazonAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilAmazonAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|     'PhutilAsanaAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilAsanaAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|     'PhutilAuthAdapter' => 'Phobject', |     'PhutilAuthAdapter' => 'Phobject', | ||||||
| @@ -12450,7 +12610,20 @@ phutil_register_library_map(array( | |||||||
|     'PhutilCalendarRootNode' => 'PhutilCalendarContainerNode', |     'PhutilCalendarRootNode' => 'PhutilCalendarContainerNode', | ||||||
|     'PhutilCalendarUserNode' => 'PhutilCalendarNode', |     'PhutilCalendarUserNode' => 'PhutilCalendarNode', | ||||||
|     'PhutilCodeSnippetContextFreeGrammar' => 'PhutilContextFreeGrammar', |     'PhutilCodeSnippetContextFreeGrammar' => 'PhutilContextFreeGrammar', | ||||||
|  |     'PhutilConsoleSyntaxHighlighter' => 'Phobject', | ||||||
|  |     'PhutilContextFreeGrammar' => 'Phobject', | ||||||
|  |     'PhutilDaemon' => 'Phobject', | ||||||
|  |     'PhutilDaemonHandle' => 'Phobject', | ||||||
|  |     'PhutilDaemonOverseer' => 'Phobject', | ||||||
|  |     'PhutilDaemonOverseerModule' => 'Phobject', | ||||||
|  |     'PhutilDaemonPool' => 'Phobject', | ||||||
|  |     'PhutilDefaultSyntaxHighlighter' => 'Phobject', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEngine' => 'PhutilSyntaxHighlighterEngine', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEnginePygmentsFuture' => 'FutureProxy', | ||||||
|  |     'PhutilDefaultSyntaxHighlighterEngineTestCase' => 'PhutilTestCase', | ||||||
|  |     'PhutilDirectoryKeyValueCache' => 'PhutilKeyValueCache', | ||||||
|     'PhutilDisqusAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilDisqusAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|  |     'PhutilDivinerSyntaxHighlighter' => 'Phobject', | ||||||
|     'PhutilEmptyAuthAdapter' => 'PhutilAuthAdapter', |     'PhutilEmptyAuthAdapter' => 'PhutilAuthAdapter', | ||||||
|     'PhutilFacebookAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilFacebookAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|     'PhutilGitHubAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilGitHubAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
| @@ -12460,18 +12633,37 @@ phutil_register_library_map(array( | |||||||
|     'PhutilICSParserTestCase' => 'PhutilTestCase', |     'PhutilICSParserTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilICSWriter' => 'Phobject', |     'PhutilICSWriter' => 'Phobject', | ||||||
|     'PhutilICSWriterTestCase' => 'PhutilTestCase', |     'PhutilICSWriterTestCase' => 'PhutilTestCase', | ||||||
|  |     'PhutilInRequestKeyValueCache' => 'PhutilKeyValueCache', | ||||||
|  |     'PhutilInvisibleSyntaxHighlighter' => 'Phobject', | ||||||
|     'PhutilJIRAAuthAdapter' => 'PhutilOAuth1AuthAdapter', |     'PhutilJIRAAuthAdapter' => 'PhutilOAuth1AuthAdapter', | ||||||
|  |     'PhutilJSONFragmentLexerHighlighterTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilJavaCodeSnippetContextFreeGrammar' => 'PhutilCLikeCodeSnippetContextFreeGrammar', |     'PhutilJavaCodeSnippetContextFreeGrammar' => 'PhutilCLikeCodeSnippetContextFreeGrammar', | ||||||
|  |     'PhutilKeyValueCache' => 'Phobject', | ||||||
|  |     'PhutilKeyValueCacheNamespace' => 'PhutilKeyValueCacheProxy', | ||||||
|  |     'PhutilKeyValueCacheProfiler' => 'PhutilKeyValueCacheProxy', | ||||||
|  |     'PhutilKeyValueCacheProxy' => 'PhutilKeyValueCache', | ||||||
|  |     'PhutilKeyValueCacheStack' => 'PhutilKeyValueCache', | ||||||
|  |     'PhutilKeyValueCacheTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilLDAPAuthAdapter' => 'PhutilAuthAdapter', |     'PhutilLDAPAuthAdapter' => 'PhutilAuthAdapter', | ||||||
|  |     'PhutilLexerSyntaxHighlighter' => 'PhutilSyntaxHighlighter', | ||||||
|     'PhutilLipsumContextFreeGrammar' => 'PhutilContextFreeGrammar', |     'PhutilLipsumContextFreeGrammar' => 'PhutilContextFreeGrammar', | ||||||
|  |     'PhutilMarkupEngine' => 'Phobject', | ||||||
|  |     'PhutilMarkupTestCase' => 'PhutilTestCase', | ||||||
|  |     'PhutilMemcacheKeyValueCache' => 'PhutilKeyValueCache', | ||||||
|     'PhutilOAuth1AuthAdapter' => 'PhutilAuthAdapter', |     'PhutilOAuth1AuthAdapter' => 'PhutilAuthAdapter', | ||||||
|     'PhutilOAuthAuthAdapter' => 'PhutilAuthAdapter', |     'PhutilOAuthAuthAdapter' => 'PhutilAuthAdapter', | ||||||
|  |     'PhutilOnDiskKeyValueCache' => 'PhutilKeyValueCache', | ||||||
|     'PhutilPHPCodeSnippetContextFreeGrammar' => 'PhutilCLikeCodeSnippetContextFreeGrammar', |     'PhutilPHPCodeSnippetContextFreeGrammar' => 'PhutilCLikeCodeSnippetContextFreeGrammar', | ||||||
|  |     'PhutilPHPFragmentLexerHighlighterTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilPhabricatorAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilPhabricatorAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|     'PhutilProseDiff' => 'Phobject', |     'PhutilProseDiff' => 'Phobject', | ||||||
|     'PhutilProseDiffTestCase' => 'PhabricatorTestCase', |     'PhutilProseDiffTestCase' => 'PhabricatorTestCase', | ||||||
|     'PhutilProseDifferenceEngine' => 'Phobject', |     'PhutilProseDifferenceEngine' => 'Phobject', | ||||||
|  |     'PhutilPygmentizeParser' => 'Phobject', | ||||||
|  |     'PhutilPygmentizeParserTestCase' => 'PhutilTestCase', | ||||||
|  |     'PhutilPygmentsSyntaxHighlighter' => 'Phobject', | ||||||
|     'PhutilQueryString' => 'Phobject', |     'PhutilQueryString' => 'Phobject', | ||||||
|  |     'PhutilRainbowSyntaxHighlighter' => 'Phobject', | ||||||
|     'PhutilRealNameContextFreeGrammar' => 'PhutilContextFreeGrammar', |     'PhutilRealNameContextFreeGrammar' => 'PhutilContextFreeGrammar', | ||||||
|     'PhutilRemarkupAnchorRule' => 'PhutilRemarkupRule', |     'PhutilRemarkupAnchorRule' => 'PhutilRemarkupRule', | ||||||
|     'PhutilRemarkupBlockInterpreter' => 'Phobject', |     'PhutilRemarkupBlockInterpreter' => 'Phobject', | ||||||
| @@ -12507,6 +12699,8 @@ phutil_register_library_map(array( | |||||||
|     'PhutilRemarkupTableBlockRule' => 'PhutilRemarkupBlockRule', |     'PhutilRemarkupTableBlockRule' => 'PhutilRemarkupBlockRule', | ||||||
|     'PhutilRemarkupTestInterpreterRule' => 'PhutilRemarkupBlockInterpreter', |     'PhutilRemarkupTestInterpreterRule' => 'PhutilRemarkupBlockInterpreter', | ||||||
|     'PhutilRemarkupUnderlineRule' => 'PhutilRemarkupRule', |     'PhutilRemarkupUnderlineRule' => 'PhutilRemarkupRule', | ||||||
|  |     'PhutilSafeHTML' => 'Phobject', | ||||||
|  |     'PhutilSafeHTMLTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilSearchQueryCompiler' => 'Phobject', |     'PhutilSearchQueryCompiler' => 'Phobject', | ||||||
|     'PhutilSearchQueryCompilerSyntaxException' => 'Exception', |     'PhutilSearchQueryCompilerSyntaxException' => 'Exception', | ||||||
|     'PhutilSearchQueryCompilerTestCase' => 'PhutilTestCase', |     'PhutilSearchQueryCompilerTestCase' => 'PhutilTestCase', | ||||||
| @@ -12514,9 +12708,18 @@ phutil_register_library_map(array( | |||||||
|     'PhutilSearchStemmer' => 'Phobject', |     'PhutilSearchStemmer' => 'Phobject', | ||||||
|     'PhutilSearchStemmerTestCase' => 'PhutilTestCase', |     'PhutilSearchStemmerTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilSlackAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilSlackAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|  |     'PhutilSprite' => 'Phobject', | ||||||
|  |     'PhutilSpriteSheet' => 'Phobject', | ||||||
|  |     'PhutilSyntaxHighlighter' => 'Phobject', | ||||||
|  |     'PhutilSyntaxHighlighterEngine' => 'Phobject', | ||||||
|  |     'PhutilSyntaxHighlighterException' => 'Exception', | ||||||
|  |     'PhutilTranslatedHTMLTestCase' => 'PhutilTestCase', | ||||||
|     'PhutilTwitchAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilTwitchAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|     'PhutilTwitterAuthAdapter' => 'PhutilOAuth1AuthAdapter', |     'PhutilTwitterAuthAdapter' => 'PhutilOAuth1AuthAdapter', | ||||||
|     'PhutilWordPressAuthAdapter' => 'PhutilOAuthAuthAdapter', |     'PhutilWordPressAuthAdapter' => 'PhutilOAuthAuthAdapter', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighter' => 'Phobject', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighterFuture' => 'FutureProxy', | ||||||
|  |     'PhutilXHPASTSyntaxHighlighterTestCase' => 'PhutilTestCase', | ||||||
|     'PolicyLockOptionType' => 'PhabricatorConfigJSONOptionType', |     'PolicyLockOptionType' => 'PhabricatorConfigJSONOptionType', | ||||||
|     'PonderAddAnswerView' => 'AphrontView', |     'PonderAddAnswerView' => 'AphrontView', | ||||||
|     'PonderAnswer' => array( |     'PonderAnswer' => array( | ||||||
|   | |||||||
| @@ -30,6 +30,7 @@ final class AphrontRequest extends Phobject { | |||||||
|   private $controller; |   private $controller; | ||||||
|   private $uriData = array(); |   private $uriData = array(); | ||||||
|   private $cookiePrefix; |   private $cookiePrefix; | ||||||
|  |   private $submitKey; | ||||||
|  |  | ||||||
|   public function __construct($host, $path) { |   public function __construct($host, $path) { | ||||||
|     $this->host = $host; |     $this->host = $host; | ||||||
| @@ -914,5 +915,19 @@ final class AphrontRequest extends Phobject { | |||||||
|     return $future; |     return $future; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function updateEphemeralCookies() { | ||||||
|  |     $submit_cookie = PhabricatorCookies::COOKIE_SUBMIT; | ||||||
|  |  | ||||||
|  |     $submit_key = $this->getCookie($submit_cookie); | ||||||
|  |     if (strlen($submit_key)) { | ||||||
|  |       $this->clearCookie($submit_cookie); | ||||||
|  |       $this->submitKey = $submit_key; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSubmitKey() { | ||||||
|  |     return $this->submitKey; | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										85
									
								
								src/aphront/__tests__/AphrontRoutingMapTestCase.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,85 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontRoutingMapTestCase | ||||||
|  |   extends PhabricatorTestCase { | ||||||
|  |  | ||||||
|  |   public function testRoutingMaps() { | ||||||
|  |     $count = 0; | ||||||
|  |  | ||||||
|  |     $sites = AphrontSite::getAllSites(); | ||||||
|  |     foreach ($sites as $site) { | ||||||
|  |       $maps = $site->getRoutingMaps(); | ||||||
|  |       foreach ($maps as $map) { | ||||||
|  |         foreach ($map->getRoutes() as $rule => $value) { | ||||||
|  |           $this->assertRoutable($site, $map, array(), $rule, $value); | ||||||
|  |           $count++; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!$count) { | ||||||
|  |       $this->assertSkipped( | ||||||
|  |         pht('No sites define any routing rules.')); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function assertRoutable( | ||||||
|  |     AphrontSite $site, | ||||||
|  |     AphrontRoutingMap $map, | ||||||
|  |     array $path, | ||||||
|  |     $rule, | ||||||
|  |     $value) { | ||||||
|  |  | ||||||
|  |     $path[] = $rule; | ||||||
|  |  | ||||||
|  |     $site_description = $site->getDescription(); | ||||||
|  |     $rule_path = implode(' > ', $path); | ||||||
|  |  | ||||||
|  |     $pattern = implode('', $path); | ||||||
|  |     $pattern = '('.$pattern.')'; | ||||||
|  |     $ok = @preg_match($pattern, ''); | ||||||
|  |  | ||||||
|  |     $this->assertTrue( | ||||||
|  |       ($ok !== false), | ||||||
|  |       pht( | ||||||
|  |         'Routing rule ("%s", for site "%s") does not compile into a '. | ||||||
|  |         'valid regular expression.', | ||||||
|  |         $rule_path, | ||||||
|  |         $site_description)); | ||||||
|  |  | ||||||
|  |     if (is_array($value)) { | ||||||
|  |       $this->assertTrue( | ||||||
|  |         (count($value) > 0), | ||||||
|  |         pht( | ||||||
|  |           'Routing rule ("%s", for site "%s") does not have any targets.', | ||||||
|  |           $rule_path, | ||||||
|  |           $site_description)); | ||||||
|  |  | ||||||
|  |       foreach ($value as $sub_rule => $sub_value) { | ||||||
|  |         $this->assertRoutable($site, $map, $path, $sub_rule, $sub_value); | ||||||
|  |       } | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (is_string($value)) { | ||||||
|  |       $this->assertTrue( | ||||||
|  |         class_exists($value), | ||||||
|  |         pht( | ||||||
|  |           'Routing rule ("%s", for site "%s") points at controller ("%s") '. | ||||||
|  |           'which does not exist.', | ||||||
|  |           $rule_path, | ||||||
|  |           $site_description, | ||||||
|  |           $value)); | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->assertFailure( | ||||||
|  |       pht( | ||||||
|  |         'Routing rule ("%s", for site "%s") points at unknown value '. | ||||||
|  |         '(of type "%s"), expected a controller class name string.', | ||||||
|  |         $rule_path, | ||||||
|  |         $site_description, | ||||||
|  |         phutil_describe_type($value))); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -27,6 +27,8 @@ final class AphrontApplicationConfiguration | |||||||
|     $request->setApplicationConfiguration($this); |     $request->setApplicationConfiguration($this); | ||||||
|     $request->setCookiePrefix($cookie_prefix); |     $request->setCookiePrefix($cookie_prefix); | ||||||
|  |  | ||||||
|  |     $request->updateEphemeralCookies(); | ||||||
|  |  | ||||||
|     return $request; |     return $request; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -771,12 +773,21 @@ final class AphrontApplicationConfiguration | |||||||
|       ); |       ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     $raw_input = @file_get_contents('php://input'); | ||||||
|  |     if ($raw_input !== false) { | ||||||
|  |       $base64_input = base64_encode($raw_input); | ||||||
|  |     } else { | ||||||
|  |       $base64_input = null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     $result = array( |     $result = array( | ||||||
|       'path' => $path, |       'path' => $path, | ||||||
|       'params' => $params, |       'params' => $params, | ||||||
|       'user' => idx($_SERVER, 'PHP_AUTH_USER'), |       'user' => idx($_SERVER, 'PHP_AUTH_USER'), | ||||||
|       'pass' => idx($_SERVER, 'PHP_AUTH_PW'), |       'pass' => idx($_SERVER, 'PHP_AUTH_PW'), | ||||||
|  |  | ||||||
|  |       'raw.base64' => $base64_input, | ||||||
|  |  | ||||||
|       // This just makes sure that the response compresses well, so reasonable |       // This just makes sure that the response compresses well, so reasonable | ||||||
|       // algorithms should want to gzip or deflate it. |       // algorithms should want to gzip or deflate it. | ||||||
|       'filler' => str_repeat('Q', 1024 * 16), |       'filler' => str_repeat('Q', 1024 * 16), | ||||||
| @@ -801,27 +812,22 @@ final class AphrontApplicationConfiguration | |||||||
|     // if we can. Among other things, this corrects variable names with |     // if we can. Among other things, this corrects variable names with | ||||||
|     // the "." character in them, which PHP normally converts into "_". |     // the "." character in them, which PHP normally converts into "_". | ||||||
|  |  | ||||||
|     // There are two major considerations here: whether the |     // If "enable_post_data_reading" is on, the documentation suggests we | ||||||
|     // `enable_post_data_reading` option is set, and whether the content |     // can not read the body. In practice, we seem to be able to. This may | ||||||
|     // type is "multipart/form-data" or not. |     // need to be resolved at some point, likely by instructing installs | ||||||
|  |     // to disable this option. | ||||||
|     // If `enable_post_data_reading` is off, we're free to read the entire |  | ||||||
|     // raw request body and parse it -- and we must, because $_POST and |  | ||||||
|     // $_FILES are not built for us. If `enable_post_data_reading` is on, |  | ||||||
|     // which is the default, we may not be able to read the body (the |  | ||||||
|     // documentation says we can't, but empirically we can at least some |  | ||||||
|     // of the time). |  | ||||||
|  |  | ||||||
|     // If the content type is "multipart/form-data", we need to build both |     // If the content type is "multipart/form-data", we need to build both | ||||||
|     // $_POST and $_FILES, which is involved. The body itself is also more |     // $_POST and $_FILES, which is involved. The body itself is also more | ||||||
|     // difficult to parse than other requests. |     // difficult to parse than other requests. | ||||||
|  |  | ||||||
|     $raw_input = PhabricatorStartup::getRawInput(); |     $raw_input = PhabricatorStartup::getRawInput(); | ||||||
|     $parser = new PhutilQueryStringParser(); |     $parser = new PhutilQueryStringParser(); | ||||||
|  |  | ||||||
|     if (strlen($raw_input)) { |     if (strlen($raw_input)) { | ||||||
|       $content_type = idx($_SERVER, 'CONTENT_TYPE'); |       $content_type = idx($_SERVER, 'CONTENT_TYPE'); | ||||||
|       $is_multipart = preg_match('@^multipart/form-data@i', $content_type); |       $is_multipart = preg_match('@^multipart/form-data@i', $content_type); | ||||||
|       if ($is_multipart && !ini_get('enable_post_data_reading')) { |       if ($is_multipart) { | ||||||
|         $multipart_parser = id(new AphrontMultipartParser()) |         $multipart_parser = id(new AphrontMultipartParser()) | ||||||
|           ->setContentType($content_type); |           ->setContentType($content_type); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										150
									
								
								src/aphront/headerparser/AphrontHTTPHeaderParser.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,150 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontHTTPHeaderParser extends Phobject { | ||||||
|  |  | ||||||
|  |   private $name; | ||||||
|  |   private $content; | ||||||
|  |   private $pairs; | ||||||
|  |  | ||||||
|  |   public function parseRawHeader($raw_header) { | ||||||
|  |     $this->name = null; | ||||||
|  |     $this->content = null; | ||||||
|  |  | ||||||
|  |     $parts = explode(':', $raw_header, 2); | ||||||
|  |     $this->name = trim($parts[0]); | ||||||
|  |     if (count($parts) > 1) { | ||||||
|  |       $this->content = trim($parts[1]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->pairs = null; | ||||||
|  |  | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getHeaderName() { | ||||||
|  |     $this->requireParse(); | ||||||
|  |     return $this->name; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getHeaderContent() { | ||||||
|  |     $this->requireParse(); | ||||||
|  |     return $this->content; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getHeaderContentAsPairs() { | ||||||
|  |     $content = $this->getHeaderContent(); | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     $state = 'prekey'; | ||||||
|  |     $length = strlen($content); | ||||||
|  |  | ||||||
|  |     $pair_name = null; | ||||||
|  |     $pair_value = null; | ||||||
|  |  | ||||||
|  |     $pairs = array(); | ||||||
|  |     $ii = 0; | ||||||
|  |     while ($ii < $length) { | ||||||
|  |       $c = $content[$ii]; | ||||||
|  |  | ||||||
|  |       switch ($state) { | ||||||
|  |         case 'prekey'; | ||||||
|  |           // We're eating space in front of a key. | ||||||
|  |           if ($c == ' ') { | ||||||
|  |             $ii++; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |           $pair_name = ''; | ||||||
|  |           $state = 'key'; | ||||||
|  |           break; | ||||||
|  |         case 'key'; | ||||||
|  |           // We're parsing a key name until we find "=" or ";". | ||||||
|  |           if ($c == ';') { | ||||||
|  |             $state = 'done'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if ($c == '=') { | ||||||
|  |             $ii++; | ||||||
|  |             $state = 'value'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           $ii++; | ||||||
|  |           $pair_name .= $c; | ||||||
|  |           break; | ||||||
|  |         case 'value': | ||||||
|  |           // We found an "=", so now figure out if the value is quoted | ||||||
|  |           // or not. | ||||||
|  |           if ($c == '"') { | ||||||
|  |             $ii++; | ||||||
|  |             $state = 'quoted'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |           $state = 'unquoted'; | ||||||
|  |           break; | ||||||
|  |         case 'quoted': | ||||||
|  |           // We're in a quoted string, parse until we find the closing quote. | ||||||
|  |           if ($c == '"') { | ||||||
|  |             $ii++; | ||||||
|  |             $state = 'done'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           $ii++; | ||||||
|  |           $pair_value .= $c; | ||||||
|  |           break; | ||||||
|  |         case 'unquoted': | ||||||
|  |           // We're in an unquoted string, parse until we find a space or a | ||||||
|  |           // semicolon. | ||||||
|  |           if ($c == ' ' || $c == ';') { | ||||||
|  |             $state = 'done'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |           $ii++; | ||||||
|  |           $pair_value .= $c; | ||||||
|  |           break; | ||||||
|  |         case 'done': | ||||||
|  |           // We parsed something, so eat any trailing whitespace and semicolons | ||||||
|  |           // and look for a new value. | ||||||
|  |           if ($c == ' ' || $c == ';') { | ||||||
|  |             $ii++; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           $pairs[] = array( | ||||||
|  |             $pair_name, | ||||||
|  |             $pair_value, | ||||||
|  |           ); | ||||||
|  |  | ||||||
|  |           $pair_name = null; | ||||||
|  |           $pair_value = null; | ||||||
|  |  | ||||||
|  |           $state = 'prekey'; | ||||||
|  |           break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($state == 'quoted') { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Header has unterminated double quote for key "%s".', | ||||||
|  |           $pair_name)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($pair_name !== null) { | ||||||
|  |       $pairs[] = array( | ||||||
|  |         $pair_name, | ||||||
|  |         $pair_value, | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $pairs; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function requireParse() { | ||||||
|  |     if ($this->name === null) { | ||||||
|  |       throw new PhutilInvalidStateException('parseRawHeader'); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,108 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontHTTPHeaderParserTestCase extends PhutilTestCase { | ||||||
|  |  | ||||||
|  |   public function testHeaderParser() { | ||||||
|  |     $cases = array( | ||||||
|  |       array( | ||||||
|  |         'Key: x; y; z', | ||||||
|  |         'Key', | ||||||
|  |         'x; y; z', | ||||||
|  |         array( | ||||||
|  |           array('x', null), | ||||||
|  |           array('y', null), | ||||||
|  |           array('z', null), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       array( | ||||||
|  |         'Content-Disposition: form-data; name="label"', | ||||||
|  |         'Content-Disposition', | ||||||
|  |         'form-data; name="label"', | ||||||
|  |         array( | ||||||
|  |           array('form-data', null), | ||||||
|  |           array('name', 'label'), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       array( | ||||||
|  |         'Content-Type: multipart/form-data; charset=utf-8', | ||||||
|  |         'Content-Type', | ||||||
|  |         'multipart/form-data; charset=utf-8', | ||||||
|  |         array( | ||||||
|  |           array('multipart/form-data', null), | ||||||
|  |           array('charset', 'utf-8'), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       array( | ||||||
|  |         'Content-Type: application/octet-stream; charset="ut', | ||||||
|  |         'Content-Type', | ||||||
|  |         'application/octet-stream; charset="ut', | ||||||
|  |         false, | ||||||
|  |       ), | ||||||
|  |       array( | ||||||
|  |         'Content-Type: multipart/form-data; boundary=ABCDEFG', | ||||||
|  |         'Content-Type', | ||||||
|  |         'multipart/form-data; boundary=ABCDEFG', | ||||||
|  |         array( | ||||||
|  |           array('multipart/form-data', null), | ||||||
|  |           array('boundary', 'ABCDEFG'), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |       array( | ||||||
|  |         'Content-Type: multipart/form-data; boundary="ABCDEFG"', | ||||||
|  |         'Content-Type', | ||||||
|  |         'multipart/form-data; boundary="ABCDEFG"', | ||||||
|  |         array( | ||||||
|  |           array('multipart/form-data', null), | ||||||
|  |           array('boundary', 'ABCDEFG'), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     foreach ($cases as $case) { | ||||||
|  |       $input = $case[0]; | ||||||
|  |       $expect_name = $case[1]; | ||||||
|  |       $expect_content = $case[2]; | ||||||
|  |  | ||||||
|  |       $parser = id(new AphrontHTTPHeaderParser()) | ||||||
|  |         ->parseRawHeader($input); | ||||||
|  |  | ||||||
|  |       $actual_name = $parser->getHeaderName(); | ||||||
|  |       $actual_content = $parser->getHeaderContent(); | ||||||
|  |  | ||||||
|  |       $this->assertEqual( | ||||||
|  |         $expect_name, | ||||||
|  |         $actual_name, | ||||||
|  |         pht('Header name for: %s', $input)); | ||||||
|  |  | ||||||
|  |       $this->assertEqual( | ||||||
|  |         $expect_content, | ||||||
|  |         $actual_content, | ||||||
|  |         pht('Header content for: %s', $input)); | ||||||
|  |  | ||||||
|  |       if (isset($case[3])) { | ||||||
|  |         $expect_pairs = $case[3]; | ||||||
|  |  | ||||||
|  |         $caught = null; | ||||||
|  |         try { | ||||||
|  |           $actual_pairs = $parser->getHeaderContentAsPairs(); | ||||||
|  |         } catch (Exception $ex) { | ||||||
|  |           $caught = $ex; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($expect_pairs === false) { | ||||||
|  |           $this->assertEqual( | ||||||
|  |             true, | ||||||
|  |             ($caught instanceof Exception), | ||||||
|  |             pht('Expect exception for header pairs of: %s', $input)); | ||||||
|  |         } else { | ||||||
|  |           $this->assertEqual( | ||||||
|  |             $expect_pairs, | ||||||
|  |             $actual_pairs, | ||||||
|  |             pht('Header pairs for: %s', $input)); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										249
									
								
								src/aphront/multipartparser/AphrontMultipartParser.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,249 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontMultipartParser extends Phobject { | ||||||
|  |  | ||||||
|  |   private $contentType; | ||||||
|  |   private $boundary; | ||||||
|  |  | ||||||
|  |   private $buffer; | ||||||
|  |   private $body; | ||||||
|  |   private $state; | ||||||
|  |  | ||||||
|  |   private $part; | ||||||
|  |   private $parts; | ||||||
|  |  | ||||||
|  |   public function setContentType($content_type) { | ||||||
|  |     $this->contentType = $content_type; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getContentType() { | ||||||
|  |     return $this->contentType; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function beginParse() { | ||||||
|  |     $content_type = $this->getContentType(); | ||||||
|  |     if ($content_type === null) { | ||||||
|  |       throw new PhutilInvalidStateException('setContentType'); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!preg_match('(^multipart/form-data)', $content_type)) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Expected "multipart/form-data" content type when executing a '. | ||||||
|  |           'multipart body read.')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $type_parts = preg_split('(\s*;\s*)', $content_type); | ||||||
|  |     $boundary = null; | ||||||
|  |     foreach ($type_parts as $type_part) { | ||||||
|  |       $matches = null; | ||||||
|  |       if (preg_match('(^boundary=(.*))', $type_part, $matches)) { | ||||||
|  |         $boundary = $matches[1]; | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($boundary === null) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht('Received "multipart/form-data" request with no "boundary".')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->parts = array(); | ||||||
|  |     $this->part = null; | ||||||
|  |  | ||||||
|  |     $this->buffer = ''; | ||||||
|  |     $this->boundary = $boundary; | ||||||
|  |  | ||||||
|  |     // We're looking for a (usually empty) body before the first boundary. | ||||||
|  |     $this->state = 'bodynewline'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function continueParse($bytes) { | ||||||
|  |     $this->buffer .= $bytes; | ||||||
|  |  | ||||||
|  |     $continue = true; | ||||||
|  |     while ($continue) { | ||||||
|  |       switch ($this->state) { | ||||||
|  |         case 'endboundary': | ||||||
|  |           // We've just parsed a boundary. Next, we expect either "--" (which | ||||||
|  |           // indicates we've reached the end of the parts) or "\r\n" (which | ||||||
|  |           // indicates we should read the headers for the next part). | ||||||
|  |  | ||||||
|  |           if (strlen($this->buffer) < 2) { | ||||||
|  |             // We don't have enough bytes yet, so wait for more. | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if (!strncmp($this->buffer, '--', 2)) { | ||||||
|  |             // This is "--" after a boundary, so we're done. We'll read the | ||||||
|  |             // rest of the body (the "epilogue") and discard it. | ||||||
|  |             $this->buffer = substr($this->buffer, 2); | ||||||
|  |             $this->state = 'epilogue'; | ||||||
|  |  | ||||||
|  |             $this->part = null; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if (!strncmp($this->buffer, "\r\n", 2)) { | ||||||
|  |             // This is "\r\n" after a boundary, so we're going to going to | ||||||
|  |             // read the headers for a part. | ||||||
|  |             $this->buffer = substr($this->buffer, 2); | ||||||
|  |             $this->state = 'header'; | ||||||
|  |  | ||||||
|  |             // Create the object to hold the part we're about to read. | ||||||
|  |             $part = new AphrontMultipartPart(); | ||||||
|  |             $this->parts[] = $part; | ||||||
|  |             $this->part = $part; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           throw new Exception( | ||||||
|  |             pht('Expected "\r\n" or "--" after multipart data boundary.')); | ||||||
|  |         case 'header': | ||||||
|  |           // We've just parsed a boundary, followed by "\r\n". We are going | ||||||
|  |           // to read the headers for this part. They are in the form of HTTP | ||||||
|  |           // headers and terminated by "\r\n". The section is terminated by | ||||||
|  |           // a line with no header on it. | ||||||
|  |  | ||||||
|  |           if (strlen($this->buffer) < 2) { | ||||||
|  |             // We don't have enough data to find a "\r\n", so wait for more. | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if (!strncmp("\r\n", $this->buffer, 2)) { | ||||||
|  |             // This line immediately began "\r\n", so we're done with parsing | ||||||
|  |             // headers. Start parsing the body. | ||||||
|  |             $this->buffer = substr($this->buffer, 2); | ||||||
|  |             $this->state = 'body'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           // This is an actual header, so look for the end of it. | ||||||
|  |           $header_len = strpos($this->buffer, "\r\n"); | ||||||
|  |           if ($header_len === false) { | ||||||
|  |             // We don't have a full header yet, so wait for more data. | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           $header_buf = substr($this->buffer, 0, $header_len); | ||||||
|  |           $this->part->appendRawHeader($header_buf); | ||||||
|  |  | ||||||
|  |           $this->buffer = substr($this->buffer, $header_len + 2); | ||||||
|  |           break; | ||||||
|  |         case 'body': | ||||||
|  |           // We've parsed a boundary and headers, and are parsing the data for | ||||||
|  |           // this part. The data is terminated by "\r\n--", then the boundary. | ||||||
|  |  | ||||||
|  |           // We'll look for "\r\n", then switch to the "bodynewline" state if | ||||||
|  |           // we find it. | ||||||
|  |  | ||||||
|  |           $marker = "\r"; | ||||||
|  |           $marker_pos = strpos($this->buffer, $marker); | ||||||
|  |  | ||||||
|  |           if ($marker_pos === false) { | ||||||
|  |             // There's no "\r" anywhere in the buffer, so we can just read it | ||||||
|  |             // as provided. Then, since we read all the data, we're done until | ||||||
|  |             // we get more. | ||||||
|  |  | ||||||
|  |             // Note that if we're in the preamble, we won't have a "part" | ||||||
|  |             // object and will just discard the data. | ||||||
|  |             if ($this->part) { | ||||||
|  |               $this->part->appendData($this->buffer); | ||||||
|  |             } | ||||||
|  |             $this->buffer = ''; | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if ($marker_pos > 0) { | ||||||
|  |             // If there are bytes before the "\r", | ||||||
|  |             if ($this->part) { | ||||||
|  |               $this->part->appendData(substr($this->buffer, 0, $marker_pos)); | ||||||
|  |             } | ||||||
|  |             $this->buffer = substr($this->buffer, $marker_pos); | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           $expect = "\r\n"; | ||||||
|  |           $expect_len = strlen($expect); | ||||||
|  |           if (strlen($this->buffer) < $expect_len) { | ||||||
|  |             // We don't have enough bytes yet to know if this is "\r\n" | ||||||
|  |             // or not. | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if (strncmp($this->buffer, $expect, $expect_len)) { | ||||||
|  |             // The next two bytes aren't "\r\n", so eat them and go looking | ||||||
|  |             // for more newlines. | ||||||
|  |             if ($this->part) { | ||||||
|  |               $this->part->appendData(substr($this->buffer, 0, $expect_len)); | ||||||
|  |             } | ||||||
|  |             $this->buffer = substr($this->buffer, $expect_len); | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           // Eat the "\r\n". | ||||||
|  |           $this->buffer = substr($this->buffer, $expect_len); | ||||||
|  |           $this->state = 'bodynewline'; | ||||||
|  |           break; | ||||||
|  |         case 'bodynewline': | ||||||
|  |           // We've parsed a newline in a body, or we just started parsing the | ||||||
|  |           // request. In either case, we're looking for "--", then the boundary. | ||||||
|  |           // If we find it, this section is done. If we don't, we consume the | ||||||
|  |           // bytes and move on. | ||||||
|  |  | ||||||
|  |           $expect = '--'.$this->boundary; | ||||||
|  |           $expect_len = strlen($expect); | ||||||
|  |  | ||||||
|  |           if (strlen($this->buffer) < $expect_len) { | ||||||
|  |             // We don't have enough bytes yet, so wait for more. | ||||||
|  |             $continue = false; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           if (strncmp($this->buffer, $expect, $expect_len)) { | ||||||
|  |             // This wasn't the boundary, so return to the "body" state and | ||||||
|  |             // consume it. (But first, we need to append the "\r\n" which we | ||||||
|  |             // ate earlier.) | ||||||
|  |             if ($this->part) { | ||||||
|  |               $this->part->appendData("\r\n"); | ||||||
|  |             } | ||||||
|  |             $this->state = 'body'; | ||||||
|  |             break; | ||||||
|  |           } | ||||||
|  |  | ||||||
|  |           // This is the boundary, so toss it and move on. | ||||||
|  |           $this->buffer = substr($this->buffer, $expect_len); | ||||||
|  |           $this->state = 'endboundary'; | ||||||
|  |           break; | ||||||
|  |         case 'epilogue': | ||||||
|  |           // We just discard any epilogue. | ||||||
|  |           $this->buffer = ''; | ||||||
|  |           $continue = false; | ||||||
|  |           break; | ||||||
|  |         default: | ||||||
|  |           throw new Exception( | ||||||
|  |             pht( | ||||||
|  |               'Unknown parser state "%s".\n', | ||||||
|  |               $this->state)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function endParse() { | ||||||
|  |     if ($this->state !== 'epilogue') { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Expected "multipart/form-data" parse to end '. | ||||||
|  |           'in state "epilogue".')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->parts; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										96
									
								
								src/aphront/multipartparser/AphrontMultipartPart.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,96 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontMultipartPart extends Phobject { | ||||||
|  |  | ||||||
|  |   private $headers = array(); | ||||||
|  |   private $value = ''; | ||||||
|  |  | ||||||
|  |   private $name; | ||||||
|  |   private $filename; | ||||||
|  |   private $tempFile; | ||||||
|  |   private $byteSize = 0; | ||||||
|  |  | ||||||
|  |   public function appendRawHeader($bytes) { | ||||||
|  |     $parser = id(new AphrontHTTPHeaderParser()) | ||||||
|  |       ->parseRawHeader($bytes); | ||||||
|  |  | ||||||
|  |     $header_name = $parser->getHeaderName(); | ||||||
|  |  | ||||||
|  |     $this->headers[] = array( | ||||||
|  |       $header_name, | ||||||
|  |       $parser->getHeaderContent(), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     if (strtolower($header_name) === 'content-disposition') { | ||||||
|  |       $pairs = $parser->getHeaderContentAsPairs(); | ||||||
|  |       foreach ($pairs as $pair) { | ||||||
|  |         list($key, $value) = $pair; | ||||||
|  |         switch ($key) { | ||||||
|  |           case 'filename': | ||||||
|  |             $this->filename = $value; | ||||||
|  |             break; | ||||||
|  |           case 'name': | ||||||
|  |             $this->name = $value; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function appendData($bytes) { | ||||||
|  |     $this->byteSize += strlen($bytes); | ||||||
|  |  | ||||||
|  |     if ($this->isVariable()) { | ||||||
|  |       $this->value .= $bytes; | ||||||
|  |     } else { | ||||||
|  |       if (!$this->tempFile) { | ||||||
|  |         $this->tempFile = new TempFile(getmypid().'.upload'); | ||||||
|  |       } | ||||||
|  |       Filesystem::appendFile($this->tempFile, $bytes); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function isVariable() { | ||||||
|  |     return ($this->filename === null); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getName() { | ||||||
|  |     return $this->name; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getVariableValue() { | ||||||
|  |     if (!$this->isVariable()) { | ||||||
|  |       throw new Exception(pht('This part is not a variable!')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->value; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getPHPFileDictionary() { | ||||||
|  |     if (!$this->tempFile) { | ||||||
|  |       $this->appendData(''); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $mime_type = 'application/octet-stream'; | ||||||
|  |     foreach ($this->headers as $header) { | ||||||
|  |       list($name, $value) = $header; | ||||||
|  |       if (strtolower($name) == 'content-type') { | ||||||
|  |         $mime_type = $value; | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return array( | ||||||
|  |       'name' => $this->filename, | ||||||
|  |       'type' => $mime_type, | ||||||
|  |       'tmp_name' => (string)$this->tempFile, | ||||||
|  |       'error' => 0, | ||||||
|  |       'size' => $this->byteSize, | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,45 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontMultipartParserTestCase extends PhutilTestCase { | ||||||
|  |  | ||||||
|  |   public function testParser() { | ||||||
|  |     $map = array( | ||||||
|  |       array( | ||||||
|  |         'data' => 'simple.txt', | ||||||
|  |         'variables' => array( | ||||||
|  |           array('a', 'b'), | ||||||
|  |         ), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     $data_dir = dirname(__FILE__).'/data/'; | ||||||
|  |     foreach ($map as $test_case) { | ||||||
|  |       $data = Filesystem::readFile($data_dir.$test_case['data']); | ||||||
|  |       $data = str_replace("\n", "\r\n", $data); | ||||||
|  |  | ||||||
|  |       $parser = id(new AphrontMultipartParser()) | ||||||
|  |         ->setContentType('multipart/form-data; boundary=ABCDEFG'); | ||||||
|  |       $parser->beginParse(); | ||||||
|  |       $parser->continueParse($data); | ||||||
|  |       $parts = $parser->endParse(); | ||||||
|  |  | ||||||
|  |       $variables = array(); | ||||||
|  |       foreach ($parts as $part) { | ||||||
|  |         if (!$part->isVariable()) { | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $variables[] = array( | ||||||
|  |           $part->getName(), | ||||||
|  |           $part->getVariableValue(), | ||||||
|  |         ); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       $expect_variables = idx($test_case, 'variables', array()); | ||||||
|  |       $this->assertEqual($expect_variables, $variables); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								src/aphront/multipartparser/__tests__/data/simple.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,5 @@ | |||||||
|  | --ABCDEFG | ||||||
|  | Content-Disposition: form-data; name="a" | ||||||
|  |  | ||||||
|  | b | ||||||
|  | --ABCDEFG-- | ||||||
							
								
								
									
										113
									
								
								src/aphront/requeststream/AphrontRequestStream.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,113 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontRequestStream extends Phobject { | ||||||
|  |  | ||||||
|  |   private $encoding; | ||||||
|  |   private $stream; | ||||||
|  |   private $closed; | ||||||
|  |   private $iterator; | ||||||
|  |  | ||||||
|  |   public function setEncoding($encoding) { | ||||||
|  |     $this->encoding = $encoding; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getEncoding() { | ||||||
|  |     return $this->encoding; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getIterator() { | ||||||
|  |     if (!$this->iterator) { | ||||||
|  |       $this->iterator = new PhutilStreamIterator($this->getStream()); | ||||||
|  |     } | ||||||
|  |     return $this->iterator; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function readData() { | ||||||
|  |     if (!$this->iterator) { | ||||||
|  |       $iterator = $this->getIterator(); | ||||||
|  |       $iterator->rewind(); | ||||||
|  |     } else { | ||||||
|  |       $iterator = $this->getIterator(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!$iterator->valid()) { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $data = $iterator->current(); | ||||||
|  |     $iterator->next(); | ||||||
|  |  | ||||||
|  |     return $data; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function getStream() { | ||||||
|  |     if (!$this->stream) { | ||||||
|  |       $this->stream = $this->newStream(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->stream; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function newStream() { | ||||||
|  |     $stream = fopen('php://input', 'rb'); | ||||||
|  |     if (!$stream) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Failed to open stream "%s" for reading.', | ||||||
|  |           'php://input')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $encoding = $this->getEncoding(); | ||||||
|  |     if ($encoding === 'gzip') { | ||||||
|  |       // This parameter is magic. Values 0-15 express a time/memory tradeoff, | ||||||
|  |       // but the largest value (15) corresponds to only 32KB of memory and | ||||||
|  |       // data encoded with a smaller window size than the one we pass can not | ||||||
|  |       // be decompressed. Always pass the maximum window size. | ||||||
|  |  | ||||||
|  |       // Additionally, you can add 16 (to enable gzip) or 32 (to enable both | ||||||
|  |       // gzip and zlib). Add 32 to support both. | ||||||
|  |       $zlib_window = 15 + 32; | ||||||
|  |  | ||||||
|  |       $ok = stream_filter_append( | ||||||
|  |         $stream, | ||||||
|  |         'zlib.inflate', | ||||||
|  |         STREAM_FILTER_READ, | ||||||
|  |         array( | ||||||
|  |           'window' => $zlib_window, | ||||||
|  |         )); | ||||||
|  |       if (!$ok) { | ||||||
|  |         throw new Exception( | ||||||
|  |           pht( | ||||||
|  |             'Failed to append filter "%s" to input stream while processing '. | ||||||
|  |             'a request with "%s" encoding.', | ||||||
|  |             'zlib.inflate', | ||||||
|  |             $encoding)); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $stream; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public static function supportsGzip() { | ||||||
|  |     if (!function_exists('gzencode') || !function_exists('gzdecode')) { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $has_zlib = false; | ||||||
|  |  | ||||||
|  |     // NOTE: At least locally, this returns "zlib.*", which is not terribly | ||||||
|  |     // reassuring. We care about "zlib.inflate". | ||||||
|  |  | ||||||
|  |     $filters = stream_get_filters(); | ||||||
|  |     foreach ($filters as $filter) { | ||||||
|  |       if (!strncasecmp($filter, 'zlib.', strlen('zlib.'))) { | ||||||
|  |         $has_zlib = true; | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $has_zlib; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -61,11 +61,17 @@ final class AphrontHTTPProxyResponse extends AphrontResponse { | |||||||
|     // Strip "Transfer-Encoding" headers. Particularly, the server we proxied |     // Strip "Transfer-Encoding" headers. Particularly, the server we proxied | ||||||
|     // may have chunked the response, but cURL will already have un-chunked it. |     // may have chunked the response, but cURL will already have un-chunked it. | ||||||
|     // If we emit the header and unchunked data, the response becomes invalid. |     // If we emit the header and unchunked data, the response becomes invalid. | ||||||
|  |  | ||||||
|  |     // See T13517. Strip "Content-Encoding" and "Content-Length" headers, since | ||||||
|  |     // they may reflect compressed content. | ||||||
|  |  | ||||||
|     foreach ($headers as $key => $header) { |     foreach ($headers as $key => $header) { | ||||||
|       list($header_head, $header_body) = $header; |       list($header_head, $header_body) = $header; | ||||||
|       $header_head = phutil_utf8_strtolower($header_head); |       $header_head = phutil_utf8_strtolower($header_head); | ||||||
|       switch ($header_head) { |       switch ($header_head) { | ||||||
|         case 'transfer-encoding': |         case 'transfer-encoding': | ||||||
|  |         case 'content-encoding': | ||||||
|  |         case 'content-length': | ||||||
|           unset($headers[$key]); |           unset($headers[$key]); | ||||||
|           break; |           break; | ||||||
|       } |       } | ||||||
|   | |||||||
| @@ -31,10 +31,10 @@ final class AphrontJSONResponse extends AphrontResponse { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getHeaders() { |   public function getHeaders() { | ||||||
|     $headers = array( |     $headers = parent::getHeaders(); | ||||||
|       array('Content-Type', 'application/json'), |  | ||||||
|     ); |     $headers[] = array('Content-Type', 'application/json'); | ||||||
|     $headers = array_merge(parent::getHeaders(), $headers); |  | ||||||
|     return $headers; |     return $headers; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ abstract class AphrontResponse extends Phobject { | |||||||
|   private $contentSecurityPolicyURIs; |   private $contentSecurityPolicyURIs; | ||||||
|   private $disableContentSecurityPolicy; |   private $disableContentSecurityPolicy; | ||||||
|   protected $frameable; |   protected $frameable; | ||||||
|  |   private $headers = array(); | ||||||
|  |  | ||||||
|   public function setRequest($request) { |   public function setRequest($request) { | ||||||
|     $this->request = $request; |     $this->request = $request; | ||||||
| @@ -49,6 +49,11 @@ abstract class AphrontResponse extends Phobject { | |||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   final public function addHeader($key, $value) { | ||||||
|  |     $this->headers[] = array($key, $value); | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
| /* -(  Content  )------------------------------------------------------------ */ | /* -(  Content  )------------------------------------------------------------ */ | ||||||
|  |  | ||||||
| @@ -105,6 +110,10 @@ abstract class AphrontResponse extends Phobject { | |||||||
|  |  | ||||||
|     $headers[] = array('Referrer-Policy', 'no-referrer'); |     $headers[] = array('Referrer-Policy', 'no-referrer'); | ||||||
|  |  | ||||||
|  |     foreach ($this->headers as $header) { | ||||||
|  |       $headers[] = $header; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return $headers; |     return $headers; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -417,6 +426,11 @@ abstract class AphrontResponse extends Phobject { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function willBeginWrite() { |   public function willBeginWrite() { | ||||||
|  |     // If we've already sent headers, these "ini_set()" calls will warn that | ||||||
|  |     // they have no effect. Today, this always happens because we're inside | ||||||
|  |     // a unit test, so just skip adjusting the setting. | ||||||
|  |  | ||||||
|  |     if (!headers_sent()) { | ||||||
|       if ($this->shouldCompressResponse()) { |       if ($this->shouldCompressResponse()) { | ||||||
|         // Enable automatic compression here. Webservers sometimes do this for |         // Enable automatic compression here. Webservers sometimes do this for | ||||||
|         // us, but we now detect the absence of compression and warn users about |         // us, but we now detect the absence of compression and warn users about | ||||||
| @@ -426,6 +440,7 @@ abstract class AphrontResponse extends Phobject { | |||||||
|         ini_set('zlib.output_compression', 0); |         ini_set('zlib.output_compression', 0); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public function didCompleteWrite($aborted) { |   public function didCompleteWrite($aborted) { | ||||||
|     return; |     return; | ||||||
|   | |||||||
							
								
								
									
										76
									
								
								src/aphront/sprite/PhutilSprite.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,76 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * NOTE: This is very new and unstable. | ||||||
|  |  */ | ||||||
|  | final class PhutilSprite extends Phobject { | ||||||
|  |  | ||||||
|  |   private $sourceFiles = array(); | ||||||
|  |   private $sourceX; | ||||||
|  |   private $sourceY; | ||||||
|  |   private $sourceW; | ||||||
|  |   private $sourceH; | ||||||
|  |   private $targetCSS; | ||||||
|  |   private $spriteSheet; | ||||||
|  |   private $name; | ||||||
|  |  | ||||||
|  |   public function setName($name) { | ||||||
|  |     $this->name = $name; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getName() { | ||||||
|  |     return $this->name; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setTargetCSS($target_css) { | ||||||
|  |     $this->targetCSS = $target_css; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getTargetCSS() { | ||||||
|  |     return $this->targetCSS; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setSourcePosition($x, $y) { | ||||||
|  |     $this->sourceX = $x; | ||||||
|  |     $this->sourceY = $y; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setSourceSize($w, $h) { | ||||||
|  |     $this->sourceW = $w; | ||||||
|  |     $this->sourceH = $h; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSourceH() { | ||||||
|  |     return $this->sourceH; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSourceW() { | ||||||
|  |     return $this->sourceW; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSourceY() { | ||||||
|  |     return $this->sourceY; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSourceX() { | ||||||
|  |     return $this->sourceX; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setSourceFile($source_file, $scale = 1) { | ||||||
|  |     $this->sourceFiles[$scale] = $source_file; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getSourceFile($scale) { | ||||||
|  |     if (empty($this->sourceFiles[$scale])) { | ||||||
|  |       throw new Exception(pht("No source file for scale '%s'!", $scale)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->sourceFiles[$scale]; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										385
									
								
								src/aphront/sprite/PhutilSpriteSheet.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,385 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * NOTE: This is very new and unstable. | ||||||
|  |  */ | ||||||
|  | final class PhutilSpriteSheet extends Phobject { | ||||||
|  |  | ||||||
|  |   const MANIFEST_VERSION = 1; | ||||||
|  |  | ||||||
|  |   const TYPE_STANDARD = 'standard'; | ||||||
|  |   const TYPE_REPEAT_X = 'repeat-x'; | ||||||
|  |   const TYPE_REPEAT_Y = 'repeat-y'; | ||||||
|  |  | ||||||
|  |   private $sprites = array(); | ||||||
|  |   private $sources = array(); | ||||||
|  |   private $hashes  = array(); | ||||||
|  |   private $cssHeader; | ||||||
|  |   private $generated; | ||||||
|  |   private $scales = array(1); | ||||||
|  |   private $type = self::TYPE_STANDARD; | ||||||
|  |   private $basePath; | ||||||
|  |  | ||||||
|  |   private $css; | ||||||
|  |   private $images; | ||||||
|  |  | ||||||
|  |   public function addSprite(PhutilSprite $sprite) { | ||||||
|  |     $this->generated = false; | ||||||
|  |     $this->sprites[] = $sprite; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setCSSHeader($header) { | ||||||
|  |     $this->generated = false; | ||||||
|  |     $this->cssHeader = $header; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setScales(array $scales) { | ||||||
|  |     $this->scales = array_values($scales); | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getScales() { | ||||||
|  |     return $this->scales; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setSheetType($type) { | ||||||
|  |     $this->type = $type; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setBasePath($base_path) { | ||||||
|  |     $this->basePath = $base_path; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function generate() { | ||||||
|  |     if ($this->generated) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $multi_row = true; | ||||||
|  |     $multi_col = true; | ||||||
|  |     $margin_w = 1; | ||||||
|  |     $margin_h = 1; | ||||||
|  |  | ||||||
|  |     $type = $this->type; | ||||||
|  |     switch ($type) { | ||||||
|  |       case self::TYPE_STANDARD: | ||||||
|  |         break; | ||||||
|  |       case self::TYPE_REPEAT_X: | ||||||
|  |         $multi_col = false; | ||||||
|  |         $margin_w = 0; | ||||||
|  |  | ||||||
|  |         $width = null; | ||||||
|  |         foreach ($this->sprites as $sprite) { | ||||||
|  |           if ($width === null) { | ||||||
|  |             $width = $sprite->getSourceW(); | ||||||
|  |           } else if ($width !== $sprite->getSourceW()) { | ||||||
|  |             throw new Exception( | ||||||
|  |               pht( | ||||||
|  |                 "All sprites in a '%s' sheet must have the same width.", | ||||||
|  |                 'repeat-x')); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       case self::TYPE_REPEAT_Y: | ||||||
|  |         $multi_row = false; | ||||||
|  |         $margin_h = 0; | ||||||
|  |  | ||||||
|  |         $height = null; | ||||||
|  |         foreach ($this->sprites as $sprite) { | ||||||
|  |           if ($height === null) { | ||||||
|  |             $height = $sprite->getSourceH(); | ||||||
|  |           } else if ($height !== $sprite->getSourceH()) { | ||||||
|  |             throw new Exception( | ||||||
|  |               pht( | ||||||
|  |                 "All sprites in a '%s' sheet must have the same height.", | ||||||
|  |                 'repeat-y')); | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         break; | ||||||
|  |       default: | ||||||
|  |         throw new Exception(pht("Unknown sprite sheet type '%s'!", $type)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     $css = array(); | ||||||
|  |     if ($this->cssHeader) { | ||||||
|  |       $css[] = $this->cssHeader; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $out_w = 0; | ||||||
|  |     $out_h = 0; | ||||||
|  |  | ||||||
|  |     // Lay out the sprite sheet. We attempt to build a roughly square sheet | ||||||
|  |     // so it's easier to manage, since 2000x20 is more cumbersome for humans | ||||||
|  |     // to deal with than 200x200. | ||||||
|  |     // | ||||||
|  |     // To do this, we use a simple greedy algorithm, adding sprites one at a | ||||||
|  |     // time. For each sprite, if the sheet is at least as wide as it is tall | ||||||
|  |     // we create a new row. Otherwise, we try to add it to an existing row. | ||||||
|  |     // | ||||||
|  |     // This isn't optimal, but does a reasonable job in most cases and isn't | ||||||
|  |     // too messy. | ||||||
|  |  | ||||||
|  |     // Group the sprites by their sizes. We lay them out in the sheet as | ||||||
|  |     // boxes, but then put them into the boxes in the order they were added | ||||||
|  |     // so similar sprites end up nearby on the final sheet. | ||||||
|  |     $boxes = array(); | ||||||
|  |     foreach (array_reverse($this->sprites) as $sprite) { | ||||||
|  |       $s_w = $sprite->getSourceW() + $margin_w; | ||||||
|  |       $s_h = $sprite->getSourceH() + $margin_h; | ||||||
|  |       $boxes[$s_w][$s_h][] = $sprite; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $rows = array(); | ||||||
|  |     foreach ($this->sprites as $sprite) { | ||||||
|  |       $s_w = $sprite->getSourceW() + $margin_w; | ||||||
|  |       $s_h = $sprite->getSourceH() + $margin_h; | ||||||
|  |  | ||||||
|  |       // Choose a row for this sprite. | ||||||
|  |       $maybe = array(); | ||||||
|  |       foreach ($rows as $key => $row) { | ||||||
|  |         if ($row['h'] < $s_h) { | ||||||
|  |           // We can only add it to a row if the row is at least as tall as the | ||||||
|  |           // sprite. | ||||||
|  |           continue; | ||||||
|  |         } | ||||||
|  |         // We prefer rows which have the same height as the sprite, and then | ||||||
|  |         // rows which aren't yet very wide. | ||||||
|  |         $wasted_v = ($row['h'] - $s_h); | ||||||
|  |         $wasted_h = ($row['w'] / $out_w); | ||||||
|  |         $maybe[$key] = $wasted_v + $wasted_h; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       $row_key = null; | ||||||
|  |       if ($maybe && $multi_col) { | ||||||
|  |         // If there were any candidate rows, pick the best one. | ||||||
|  |         asort($maybe); | ||||||
|  |         $row_key = head_key($maybe); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if ($row_key !== null && $multi_row) { | ||||||
|  |         // If there's a candidate row, but adding the sprite to it would make | ||||||
|  |         // the sprite wider than it is tall, create a new row instead. This | ||||||
|  |         // generally keeps the sprite square-ish. | ||||||
|  |         if ($rows[$row_key]['w'] + $s_w > $out_h) { | ||||||
|  |           $row_key = null; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if ($row_key === null) { | ||||||
|  |         // Add a new row. | ||||||
|  |         $rows[] = array( | ||||||
|  |           'w'       => 0, | ||||||
|  |           'h'       => $s_h, | ||||||
|  |           'boxes'   => array(), | ||||||
|  |         ); | ||||||
|  |         $row_key = last_key($rows); | ||||||
|  |         $out_h += $s_h; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Add the sprite box to the row. | ||||||
|  |       $row = $rows[$row_key]; | ||||||
|  |       $row['w'] += $s_w; | ||||||
|  |       $row['boxes'][] = array($s_w, $s_h); | ||||||
|  |       $rows[$row_key] = $row; | ||||||
|  |  | ||||||
|  |       $out_w = max($row['w'], $out_w); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $images = array(); | ||||||
|  |     foreach ($this->scales as $scale) { | ||||||
|  |       $img = imagecreatetruecolor($out_w * $scale, $out_h * $scale); | ||||||
|  |       imagesavealpha($img, true); | ||||||
|  |       imagefill($img, 0, 0, imagecolorallocatealpha($img, 0, 0, 0, 127)); | ||||||
|  |  | ||||||
|  |       $images[$scale] = $img; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     // Put the shorter rows first. At the same height, put the wider rows first. | ||||||
|  |     // This makes the resulting sheet more human-readable. | ||||||
|  |     foreach ($rows as $key => $row) { | ||||||
|  |       $rows[$key]['sort'] = $row['h'] + (1 - ($row['w'] / $out_w)); | ||||||
|  |     } | ||||||
|  |     $rows = isort($rows, 'sort'); | ||||||
|  |  | ||||||
|  |     $pos_x = 0; | ||||||
|  |     $pos_y = 0; | ||||||
|  |     $rules = array(); | ||||||
|  |     foreach ($rows as $row) { | ||||||
|  |       $max_h = 0; | ||||||
|  |       foreach ($row['boxes'] as $box) { | ||||||
|  |         $sprite = array_pop($boxes[$box[0]][$box[1]]); | ||||||
|  |  | ||||||
|  |         foreach ($images as $scale => $img) { | ||||||
|  |           $src = $this->loadSource($sprite, $scale); | ||||||
|  |           imagecopy( | ||||||
|  |             $img, | ||||||
|  |             $src, | ||||||
|  |             $scale * $pos_x,                $scale * $pos_y, | ||||||
|  |             $scale * $sprite->getSourceX(), $scale * $sprite->getSourceY(), | ||||||
|  |             $scale * $sprite->getSourceW(), $scale * $sprite->getSourceH()); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $rule = $sprite->getTargetCSS(); | ||||||
|  |         $cssx = (-$pos_x).'px'; | ||||||
|  |         $cssy = (-$pos_y).'px'; | ||||||
|  |  | ||||||
|  |         $rules[$sprite->getName()] = "{$rule} {\n". | ||||||
|  |           "  background-position: {$cssx} {$cssy};\n}"; | ||||||
|  |  | ||||||
|  |         $pos_x += $sprite->getSourceW() + $margin_w; | ||||||
|  |         $max_h = max($max_h, $sprite->getSourceH()); | ||||||
|  |       } | ||||||
|  |       $pos_x = 0; | ||||||
|  |       $pos_y += $max_h + $margin_h; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Generate CSS rules in input order. | ||||||
|  |     foreach ($this->sprites as $sprite) { | ||||||
|  |       $css[] = $rules[$sprite->getName()]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->images = $images; | ||||||
|  |     $this->css = implode("\n\n", $css)."\n"; | ||||||
|  |     $this->generated = true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function generateImage($path, $scale = 1) { | ||||||
|  |     $this->generate(); | ||||||
|  |     $this->log(pht("Writing sprite '%s'...", $path)); | ||||||
|  |     imagepng($this->images[$scale], $path); | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function generateCSS($path) { | ||||||
|  |     $this->generate(); | ||||||
|  |     $this->log(pht("Writing CSS '%s'...", $path)); | ||||||
|  |  | ||||||
|  |     $out = $this->css; | ||||||
|  |     $out = str_replace('{X}', imagesx($this->images[1]), $out); | ||||||
|  |     $out = str_replace('{Y}', imagesy($this->images[1]), $out); | ||||||
|  |  | ||||||
|  |     Filesystem::writeFile($path, $out); | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function needsRegeneration(array $manifest) { | ||||||
|  |     return ($this->buildManifest() !== $manifest); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function buildManifest() { | ||||||
|  |     $output = array(); | ||||||
|  |     foreach ($this->sprites as $sprite) { | ||||||
|  |       $output[$sprite->getName()] = array( | ||||||
|  |         'name' => $sprite->getName(), | ||||||
|  |         'rule' => $sprite->getTargetCSS(), | ||||||
|  |         'hash' => $this->loadSourceHash($sprite), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ksort($output); | ||||||
|  |  | ||||||
|  |     $data = array( | ||||||
|  |       'version' => self::MANIFEST_VERSION, | ||||||
|  |       'sprites' => $output, | ||||||
|  |       'scales'  => $this->scales, | ||||||
|  |       'header'  => $this->cssHeader, | ||||||
|  |       'type'    => $this->type, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     return $data; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function generateManifest($path) { | ||||||
|  |     $data = $this->buildManifest(); | ||||||
|  |  | ||||||
|  |     $json = new PhutilJSON(); | ||||||
|  |     $data = $json->encodeFormatted($data); | ||||||
|  |     Filesystem::writeFile($path, $data); | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function log($message) { | ||||||
|  |     echo $message."\n"; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function loadSourceHash(PhutilSprite $sprite) { | ||||||
|  |     $inputs = array(); | ||||||
|  |  | ||||||
|  |     foreach ($this->scales as $scale) { | ||||||
|  |       $file = $sprite->getSourceFile($scale); | ||||||
|  |  | ||||||
|  |       // If two users have a project in different places, like: | ||||||
|  |       // | ||||||
|  |       //    /home/alincoln/project | ||||||
|  |       //    /home/htaft/project | ||||||
|  |       // | ||||||
|  |       // ...we want to ignore the `/home/alincoln` part when hashing the sheet, | ||||||
|  |       // since the sprites don't change when the project directory moves. If | ||||||
|  |       // the base path is set, build the hashes using paths relative to the | ||||||
|  |       // base path. | ||||||
|  |  | ||||||
|  |       $file_key = $file; | ||||||
|  |       if ($this->basePath) { | ||||||
|  |         $file_key = Filesystem::readablePath($file, $this->basePath); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       if (empty($this->hashes[$file_key])) { | ||||||
|  |         $this->hashes[$file_key] = md5(Filesystem::readFile($file)); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       $inputs[] = $file_key; | ||||||
|  |       $inputs[] = $this->hashes[$file_key]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $inputs[] = $sprite->getSourceX(); | ||||||
|  |     $inputs[] = $sprite->getSourceY(); | ||||||
|  |     $inputs[] = $sprite->getSourceW(); | ||||||
|  |     $inputs[] = $sprite->getSourceH(); | ||||||
|  |  | ||||||
|  |     return md5(implode(':', $inputs)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function loadSource(PhutilSprite $sprite, $scale) { | ||||||
|  |     $file = $sprite->getSourceFile($scale); | ||||||
|  |     if (empty($this->sources[$file])) { | ||||||
|  |       $data = Filesystem::readFile($file); | ||||||
|  |       $image = imagecreatefromstring($data); | ||||||
|  |       $this->sources[$file] = array( | ||||||
|  |         'image' => $image, | ||||||
|  |         'x'     => imagesx($image), | ||||||
|  |         'y'     => imagesy($image), | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $s_w = $sprite->getSourceW() * $scale; | ||||||
|  |     $i_w = $this->sources[$file]['x']; | ||||||
|  |     if ($s_w > $i_w) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           "Sprite source for '%s' is too small (expected width %d, found %d).", | ||||||
|  |           $file, | ||||||
|  |           $s_w, | ||||||
|  |           $i_w)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $s_h = $sprite->getSourceH() * $scale; | ||||||
|  |     $i_h = $this->sources[$file]['y']; | ||||||
|  |     if ($s_h > $i_h) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           "Sprite source for '%s' is too small (expected height %d, found %d).", | ||||||
|  |           $file, | ||||||
|  |           $s_h, | ||||||
|  |           $i_h)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->sources[$file]['image']; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -0,0 +1,9 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class AphrontScopedUnguardedWriteCapability extends Phobject { | ||||||
|  |  | ||||||
|  |   public function __destruct() { | ||||||
|  |     AphrontWriteGuard::endUnguardedWrites(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										267
									
								
								src/aphront/writeguard/AphrontWriteGuard.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,267 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Guard writes against CSRF. The Aphront structure takes care of most of this | ||||||
|  |  * for you, you just need to call: | ||||||
|  |  * | ||||||
|  |  *    AphrontWriteGuard::willWrite(); | ||||||
|  |  * | ||||||
|  |  * ...before executing a write against any new kind of storage engine. MySQL | ||||||
|  |  * databases and the default file storage engines are already covered, but if | ||||||
|  |  * you introduce new types of datastores make sure their writes are guarded. If | ||||||
|  |  * you don't guard writes and make a mistake doing CSRF checks in a controller, | ||||||
|  |  * a CSRF vulnerability can escape undetected. | ||||||
|  |  * | ||||||
|  |  * If you need to execute writes on a page which doesn't have CSRF tokens (for | ||||||
|  |  * example, because you need to do logging), you can temporarily disable the | ||||||
|  |  * write guard by calling: | ||||||
|  |  * | ||||||
|  |  *    AphrontWriteGuard::beginUnguardedWrites(); | ||||||
|  |  *    do_logging_write(); | ||||||
|  |  *    AphrontWriteGuard::endUnguardedWrites(); | ||||||
|  |  * | ||||||
|  |  * This is dangerous, because it disables the backup layer of CSRF protection | ||||||
|  |  * this class provides. You should need this only very, very rarely. | ||||||
|  |  * | ||||||
|  |  * @task protect  Protecting Writes | ||||||
|  |  * @task disable  Disabling Protection | ||||||
|  |  * @task manage   Managing Write Guards | ||||||
|  |  * @task internal Internals | ||||||
|  |  */ | ||||||
|  | final class AphrontWriteGuard extends Phobject { | ||||||
|  |  | ||||||
|  |   private static $instance; | ||||||
|  |   private static $allowUnguardedWrites = false; | ||||||
|  |  | ||||||
|  |   private $callback; | ||||||
|  |   private $allowDepth = 0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -(  Managing Write Guards  )---------------------------------------------- */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Construct a new write guard for a request. Only one write guard may be | ||||||
|  |    * active at a time. You must explicitly call @{method:dispose} when you are | ||||||
|  |    * done with a write guard: | ||||||
|  |    * | ||||||
|  |    *    $guard = new AphrontWriteGuard($callback); | ||||||
|  |    *    // ... | ||||||
|  |    *    $guard->dispose(); | ||||||
|  |    * | ||||||
|  |    * Normally, you do not need to manage guards yourself -- the Aphront stack | ||||||
|  |    * handles it for you. | ||||||
|  |    * | ||||||
|  |    * This class accepts a callback, which will be invoked when a write is | ||||||
|  |    * attempted. The callback should validate the presence of a CSRF token in | ||||||
|  |    * the request, or abort the request (e.g., by throwing an exception) if a | ||||||
|  |    * valid token isn't present. | ||||||
|  |    * | ||||||
|  |    * @param   callable CSRF callback. | ||||||
|  |    * @return  this | ||||||
|  |    * @task    manage | ||||||
|  |    */ | ||||||
|  |   public function __construct($callback) { | ||||||
|  |     if (self::$instance) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'An %s already exists. Dispose of the previous guard '. | ||||||
|  |           'before creating a new one.', | ||||||
|  |           __CLASS__)); | ||||||
|  |     } | ||||||
|  |     if (self::$allowUnguardedWrites) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'An %s is being created in a context which permits '. | ||||||
|  |           'unguarded writes unconditionally. This is not allowed and '. | ||||||
|  |           'indicates a serious error.', | ||||||
|  |           __CLASS__)); | ||||||
|  |     } | ||||||
|  |     $this->callback = $callback; | ||||||
|  |     self::$instance = $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Dispose of the active write guard. You must call this method when you are | ||||||
|  |    * done with a write guard. You do not normally need to call this yourself. | ||||||
|  |    * | ||||||
|  |    * @return void | ||||||
|  |    * @task manage | ||||||
|  |    */ | ||||||
|  |   public function dispose() { | ||||||
|  |     if (!self::$instance) { | ||||||
|  |       throw new Exception(pht( | ||||||
|  |         'Attempting to dispose of write guard, but no write guard is active!')); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($this->allowDepth > 0) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Imbalanced %s: more %s calls than %s calls.', | ||||||
|  |           __CLASS__, | ||||||
|  |           'beginUnguardedWrites()', | ||||||
|  |           'endUnguardedWrites()')); | ||||||
|  |     } | ||||||
|  |     self::$instance = null; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Determine if there is an active write guard. | ||||||
|  |    * | ||||||
|  |    * @return bool | ||||||
|  |    * @task manage | ||||||
|  |    */ | ||||||
|  |   public static function isGuardActive() { | ||||||
|  |     return (bool)self::$instance; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Return on instance of AphrontWriteGuard if it's active, or null | ||||||
|  |    * | ||||||
|  |    * @return AphrontWriteGuard|null | ||||||
|  |    */ | ||||||
|  |   public static function getInstance() { | ||||||
|  |     return self::$instance; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -(  Protecting Writes  )-------------------------------------------------- */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Declare intention to perform a write, validating that writes are allowed. | ||||||
|  |    * You should call this method before executing a write whenever you implement | ||||||
|  |    * a new storage engine where information can be permanently kept. | ||||||
|  |    * | ||||||
|  |    * Writes are permitted if: | ||||||
|  |    * | ||||||
|  |    *   - The request has valid CSRF tokens. | ||||||
|  |    *   - Unguarded writes have been temporarily enabled by a call to | ||||||
|  |    *     @{method:beginUnguardedWrites}. | ||||||
|  |    *   - All write guarding has been disabled with | ||||||
|  |    *     @{method:allowDangerousUnguardedWrites}. | ||||||
|  |    * | ||||||
|  |    * If none of these conditions are true, this method will throw and prevent | ||||||
|  |    * the write. | ||||||
|  |    * | ||||||
|  |    * @return void | ||||||
|  |    * @task protect | ||||||
|  |    */ | ||||||
|  |   public static function willWrite() { | ||||||
|  |     if (!self::$instance) { | ||||||
|  |       if (!self::$allowUnguardedWrites) { | ||||||
|  |         throw new Exception( | ||||||
|  |           pht( | ||||||
|  |             'Unguarded write! There must be an active %s to perform writes.', | ||||||
|  |             __CLASS__)); | ||||||
|  |       } else { | ||||||
|  |         // Unguarded writes are being allowed unconditionally. | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $instance = self::$instance; | ||||||
|  |     if ($instance->allowDepth == 0) { | ||||||
|  |       call_user_func($instance->callback); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -(  Disabling Write Protection  )----------------------------------------- */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Enter a scope which permits unguarded writes. This works like | ||||||
|  |    * @{method:beginUnguardedWrites} but returns an object which will end | ||||||
|  |    * the unguarded write scope when its __destruct() method is called. This | ||||||
|  |    * is useful to more easily handle exceptions correctly in unguarded write | ||||||
|  |    * blocks: | ||||||
|  |    * | ||||||
|  |    *   // Restores the guard even if do_logging() throws. | ||||||
|  |    *   function unguarded_scope() { | ||||||
|  |    *     $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | ||||||
|  |    *     do_logging(); | ||||||
|  |    *   } | ||||||
|  |    * | ||||||
|  |    * @return AphrontScopedUnguardedWriteCapability Object which ends unguarded | ||||||
|  |    *            writes when it leaves scope. | ||||||
|  |    * @task disable | ||||||
|  |    */ | ||||||
|  |   public static function beginScopedUnguardedWrites() { | ||||||
|  |     self::beginUnguardedWrites(); | ||||||
|  |     return new AphrontScopedUnguardedWriteCapability(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Begin a block which permits unguarded writes. You should use this very | ||||||
|  |    * sparingly, and only for things like logging where CSRF is not a concern. | ||||||
|  |    * | ||||||
|  |    * You must pair every call to @{method:beginUnguardedWrites} with a call to | ||||||
|  |    * @{method:endUnguardedWrites}: | ||||||
|  |    * | ||||||
|  |    *   AphrontWriteGuard::beginUnguardedWrites(); | ||||||
|  |    *   do_logging(); | ||||||
|  |    *   AphrontWriteGuard::endUnguardedWrites(); | ||||||
|  |    * | ||||||
|  |    * @return void | ||||||
|  |    * @task disable | ||||||
|  |    */ | ||||||
|  |   public static function beginUnguardedWrites() { | ||||||
|  |     if (!self::$instance) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     self::$instance->allowDepth++; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Declare that you have finished performing unguarded writes. You must | ||||||
|  |    * call this exactly once for each call to @{method:beginUnguardedWrites}. | ||||||
|  |    * | ||||||
|  |    * @return void | ||||||
|  |    * @task disable | ||||||
|  |    */ | ||||||
|  |   public static function endUnguardedWrites() { | ||||||
|  |     if (!self::$instance) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     if (self::$instance->allowDepth <= 0) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'Imbalanced %s: more %s calls than %s calls.', | ||||||
|  |           __CLASS__, | ||||||
|  |           'endUnguardedWrites()', | ||||||
|  |           'beginUnguardedWrites()')); | ||||||
|  |     } | ||||||
|  |     self::$instance->allowDepth--; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Allow execution of unguarded writes. This is ONLY appropriate for use in | ||||||
|  |    * script contexts or other contexts where you are guaranteed to never be | ||||||
|  |    * vulnerable to CSRF concerns. Calling this method is EXTREMELY DANGEROUS | ||||||
|  |    * if you do not understand the consequences. | ||||||
|  |    * | ||||||
|  |    * If you need to perform unguarded writes on an otherwise guarded workflow | ||||||
|  |    * which is vulnerable to CSRF, use @{method:beginUnguardedWrites}. | ||||||
|  |    * | ||||||
|  |    * @return void | ||||||
|  |    * @task disable | ||||||
|  |    */ | ||||||
|  |   public static function allowDangerousUnguardedWrites($allow) { | ||||||
|  |     if (self::$instance) { | ||||||
|  |       throw new Exception( | ||||||
|  |         pht( | ||||||
|  |           'You can not unconditionally disable %s by calling %s while a write '. | ||||||
|  |           'guard is active. Use %s to temporarily allow unguarded writes.', | ||||||
|  |           __CLASS__, | ||||||
|  |           __FUNCTION__.'()', | ||||||
|  |           'beginUnguardedWrites()')); | ||||||
|  |     } | ||||||
|  |     self::$allowUnguardedWrites = true; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -10,13 +10,15 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|     $viewer = $request->getViewer(); |     $viewer = $request->getViewer(); | ||||||
|  |  | ||||||
|     $menu = id(new PHUIObjectItemListView()) |     $menu = id(new PHUIObjectItemListView()) | ||||||
|       ->setUser($viewer); |       ->setViewer($viewer) | ||||||
|  |       ->setBig(true); | ||||||
|  |  | ||||||
|     $menu->addItem( |     $menu->addItem( | ||||||
|       id(new PHUIObjectItemView()) |       id(new PHUIObjectItemView()) | ||||||
|         ->setHeader(pht('Devices')) |         ->setHeader(pht('Devices')) | ||||||
|         ->setHref($this->getApplicationURI('device/')) |         ->setHref($this->getApplicationURI('device/')) | ||||||
|         ->setImageIcon('fa-server') |         ->setImageIcon('fa-server') | ||||||
|  |         ->setClickable(true) | ||||||
|         ->addAttribute( |         ->addAttribute( | ||||||
|           pht( |           pht( | ||||||
|             'Create an inventory of physical and virtual hosts and '. |             'Create an inventory of physical and virtual hosts and '. | ||||||
| @@ -27,6 +29,7 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|         ->setHeader(pht('Services')) |         ->setHeader(pht('Services')) | ||||||
|         ->setHref($this->getApplicationURI('service/')) |         ->setHref($this->getApplicationURI('service/')) | ||||||
|         ->setImageIcon('fa-plug') |         ->setImageIcon('fa-plug') | ||||||
|  |         ->setClickable(true) | ||||||
|         ->addAttribute( |         ->addAttribute( | ||||||
|           pht( |           pht( | ||||||
|             'Create and update services, and map them to interfaces on '. |             'Create and update services, and map them to interfaces on '. | ||||||
| @@ -37,6 +40,7 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|         ->setHeader(pht('Networks')) |         ->setHeader(pht('Networks')) | ||||||
|         ->setHref($this->getApplicationURI('network/')) |         ->setHref($this->getApplicationURI('network/')) | ||||||
|         ->setImageIcon('fa-globe') |         ->setImageIcon('fa-globe') | ||||||
|  |         ->setClickable(true) | ||||||
|         ->addAttribute( |         ->addAttribute( | ||||||
|           pht( |           pht( | ||||||
|             'Manage public and private networks.'))); |             'Manage public and private networks.'))); | ||||||
| @@ -46,6 +50,7 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|         ->setHeader(pht('Namespaces')) |         ->setHeader(pht('Namespaces')) | ||||||
|         ->setHref($this->getApplicationURI('namespace/')) |         ->setHref($this->getApplicationURI('namespace/')) | ||||||
|         ->setImageIcon('fa-asterisk') |         ->setImageIcon('fa-asterisk') | ||||||
|  |         ->setClickable(true) | ||||||
|         ->addAttribute( |         ->addAttribute( | ||||||
|           pht('Control who can create new named services and devices.'))); |           pht('Control who can create new named services and devices.'))); | ||||||
|  |  | ||||||
| @@ -57,6 +62,7 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|         ->setHeader(pht('Documentation')) |         ->setHeader(pht('Documentation')) | ||||||
|         ->setHref($docs_uri) |         ->setHref($docs_uri) | ||||||
|         ->setImageIcon('fa-book') |         ->setImageIcon('fa-book') | ||||||
|  |         ->setClickable(true) | ||||||
|         ->addAttribute(pht('Browse documentation for Almanac.'))); |         ->addAttribute(pht('Browse documentation for Almanac.'))); | ||||||
|  |  | ||||||
|     $crumbs = $this->buildApplicationCrumbs(); |     $crumbs = $this->buildApplicationCrumbs(); | ||||||
| @@ -64,23 +70,20 @@ final class AlmanacConsoleController extends AlmanacController { | |||||||
|     $crumbs->setBorder(true); |     $crumbs->setBorder(true); | ||||||
|  |  | ||||||
|     $box = id(new PHUIObjectBoxView()) |     $box = id(new PHUIObjectBoxView()) | ||||||
|  |       ->setHeaderText(pht('Almanac Console')) | ||||||
|  |       ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) | ||||||
|       ->setObjectList($menu); |       ->setObjectList($menu); | ||||||
|  |  | ||||||
|     $header = id(new PHUIHeaderView()) |     $launcher_view = id(new PHUILauncherView()) | ||||||
|       ->setHeader(pht('Almanac Console')) |       ->appendChild($box); | ||||||
|       ->setHeaderIcon('fa-server'); |  | ||||||
|  |  | ||||||
|     $view = id(new PHUITwoColumnView()) |     $view = id(new PHUITwoColumnView()) | ||||||
|       ->setHeader($header) |       ->setFooter($launcher_view); | ||||||
|       ->setFooter(array( |  | ||||||
|         $box, |  | ||||||
|       )); |  | ||||||
|  |  | ||||||
|     return $this->newPage() |     return $this->newPage() | ||||||
|       ->setTitle(pht('Almanac Console')) |       ->setTitle(pht('Almanac Console')) | ||||||
|       ->setCrumbs($crumbs) |       ->setCrumbs($crumbs) | ||||||
|       ->appendChild($view); |       ->appendChild($view); | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -57,15 +57,6 @@ final class AlmanacKeys extends Phobject { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static function getClusterSSHUser() { |   public static function getClusterSSHUser() { | ||||||
|     // NOTE: When instancing, we currently use the SSH username to figure out |  | ||||||
|     // which instance you are connecting to. We can't use the host name because |  | ||||||
|     // we have no way to tell which host you think you're reaching: the SSH |  | ||||||
|     // protocol does not have a mechanism like a "Host" header. |  | ||||||
|     $username = PhabricatorEnv::getEnvConfig('cluster.instance'); |  | ||||||
|     if (strlen($username)) { |  | ||||||
|       return $username; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $username = PhabricatorEnv::getEnvConfig('diffusion.ssh-user'); |     $username = PhabricatorEnv::getEnvConfig('diffusion.ssh-user'); | ||||||
|     if (strlen($username)) { |     if (strlen($username)) { | ||||||
|       return $username; |       return $username; | ||||||
|   | |||||||
| @@ -550,11 +550,18 @@ abstract class PhabricatorAphlictManagementWorkflow | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function getStartCommand(array $server_argv) { |   private function getStartCommand(array $server_argv) { | ||||||
|  |     $launch_argv = array(); | ||||||
|  |  | ||||||
|  |     if ($this->debug) { | ||||||
|  |       $launch_argv[] = '--debug=1'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return csprintf( |     return csprintf( | ||||||
|       '%R %Ls -- %s %Ls', |       '%R %Ls -- %s %Ls %Ls', | ||||||
|       $this->getNodeBinary(), |       $this->getNodeBinary(), | ||||||
|       $this->getNodeArgv(), |       $this->getNodeArgv(), | ||||||
|       $this->getAphlictScriptPath(), |       $this->getAphlictScriptPath(), | ||||||
|  |       $launch_argv, | ||||||
|       $server_argv); |       $server_argv); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -105,6 +105,14 @@ final class PhabricatorAuditEditor | |||||||
|  |  | ||||||
|     switch ($xaction->getTransactionType()) { |     switch ($xaction->getTransactionType()) { | ||||||
|       case PhabricatorAuditActionConstants::INLINE: |       case PhabricatorAuditActionConstants::INLINE: | ||||||
|  |         $comment = $xaction->getComment(); | ||||||
|  |  | ||||||
|  |         $comment->setAttribute('editing', false); | ||||||
|  |  | ||||||
|  |         PhabricatorVersionedDraft::purgeDrafts( | ||||||
|  |           $comment->getPHID(), | ||||||
|  |           $this->getActingAsPHID()); | ||||||
|  |         return; | ||||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: |       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| @@ -232,14 +240,22 @@ final class PhabricatorAuditEditor | |||||||
|     PhabricatorLiskDAO $object, |     PhabricatorLiskDAO $object, | ||||||
|     PhabricatorApplicationTransaction $xaction) { |     PhabricatorApplicationTransaction $xaction) { | ||||||
|  |  | ||||||
|  |     $auditors_type = DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE; | ||||||
|  |  | ||||||
|     $xactions = parent::expandTransaction($object, $xaction); |     $xactions = parent::expandTransaction($object, $xaction); | ||||||
|  |  | ||||||
|     switch ($xaction->getTransactionType()) { |     switch ($xaction->getTransactionType()) { | ||||||
|       case PhabricatorAuditTransaction::TYPE_COMMIT: |       case PhabricatorAuditTransaction::TYPE_COMMIT: | ||||||
|         $request = $this->createAuditRequestTransactionFromCommitMessage( |         $phids = $this->getAuditRequestTransactionPHIDsFromCommitMessage( | ||||||
|           $object); |           $object); | ||||||
|         if ($request) { |         if ($phids) { | ||||||
|           $xactions[] = $request; |           $xactions[] = $object->getApplicationTransactionTemplate() | ||||||
|           $this->addUnmentionablePHIDs($request->getNewValue()); |             ->setTransactionType($auditors_type) | ||||||
|  |             ->setNewValue( | ||||||
|  |               array( | ||||||
|  |                 '+' => array_fuse($phids), | ||||||
|  |               )); | ||||||
|  |           $this->addUnmentionablePHIDs($phids); | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|       default: |       default: | ||||||
| @@ -268,7 +284,7 @@ final class PhabricatorAuditEditor | |||||||
|     return $xactions; |     return $xactions; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function createAuditRequestTransactionFromCommitMessage( |   private function getAuditRequestTransactionPHIDsFromCommitMessage( | ||||||
|     PhabricatorRepositoryCommit $commit) { |     PhabricatorRepositoryCommit $commit) { | ||||||
|  |  | ||||||
|     $actor = $this->getActor(); |     $actor = $this->getActor(); | ||||||
| @@ -297,12 +313,7 @@ final class PhabricatorAuditEditor | |||||||
|       return array(); |       return array(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return $commit->getApplicationTransactionTemplate() |     return $phids; | ||||||
|       ->setTransactionType(DiffusionCommitAuditorsTransaction::TRANSACTIONTYPE) |  | ||||||
|       ->setNewValue( |  | ||||||
|         array( |  | ||||||
|           '+' => array_fuse($phids), |  | ||||||
|         )); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected function sortTransactions(array $xactions) { |   protected function sortTransactions(array $xactions) { | ||||||
| @@ -405,6 +416,31 @@ final class PhabricatorAuditEditor | |||||||
|       $phid_map[] = $reverted_phids; |       $phid_map[] = $reverted_phids; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // See T13463. Copy "related task" edges from the associated revision, if | ||||||
|  |     // one exists. | ||||||
|  |  | ||||||
|  |     $revision = DiffusionCommitRevisionQuery::loadRevisionForCommit( | ||||||
|  |       $actor, | ||||||
|  |       $object); | ||||||
|  |     if ($revision) { | ||||||
|  |       $task_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( | ||||||
|  |         $revision->getPHID(), | ||||||
|  |         DifferentialRevisionHasTaskEdgeType::EDGECONST); | ||||||
|  |       $task_phids = array_fuse($task_phids); | ||||||
|  |  | ||||||
|  |       if ($task_phids) { | ||||||
|  |         $related_edge = DiffusionCommitHasTaskEdgeType::EDGECONST; | ||||||
|  |         $result[] = id(new PhabricatorAuditTransaction()) | ||||||
|  |           ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) | ||||||
|  |           ->setMetadataValue('edge:type', $related_edge) | ||||||
|  |           ->setNewValue(array('+' => $task_phids)); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       // Mark these objects as unmentionable, since the explicit relationship | ||||||
|  |       // is stronger and any mentions are redundant. | ||||||
|  |       $phid_map[] = $task_phids; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     $phid_map = array_mergev($phid_map); |     $phid_map = array_mergev($phid_map); | ||||||
|     $this->addUnmentionablePHIDs($phid_map); |     $this->addUnmentionablePHIDs($phid_map); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,27 +1,16 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| final class PhabricatorAuditInlineComment | final class PhabricatorAuditInlineComment | ||||||
|   extends Phobject |   extends PhabricatorInlineComment { | ||||||
|   implements PhabricatorInlineCommentInterface { |  | ||||||
|  |  | ||||||
|   private $proxy; |   protected function newStorageObject() { | ||||||
|   private $syntheticAuthor; |     return new PhabricatorAuditTransactionComment(); | ||||||
|   private $isGhost; |  | ||||||
|  |  | ||||||
|   public function __construct() { |  | ||||||
|     $this->proxy = new PhabricatorAuditTransactionComment(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function __clone() { |   public function getControllerURI() { | ||||||
|     $this->proxy = clone $this->proxy; |     return urisprintf( | ||||||
|   } |       '/diffusion/inline/edit/%s/', | ||||||
|  |       $this->getCommitPHID()); | ||||||
|   public function getTransactionPHID() { |  | ||||||
|     return $this->proxy->getTransactionPHID(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getTransactionComment() { |  | ||||||
|     return $this->proxy; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function supportsHiding() { |   public function supportsHiding() { | ||||||
| @@ -36,246 +25,40 @@ final class PhabricatorAuditInlineComment | |||||||
|     $content_source = PhabricatorContentSource::newForSource( |     $content_source = PhabricatorContentSource::newForSource( | ||||||
|       PhabricatorOldWorldContentSource::SOURCECONST); |       PhabricatorOldWorldContentSource::SOURCECONST); | ||||||
|  |  | ||||||
|     $this->proxy |     $this->getStorageObject() | ||||||
|       ->setViewPolicy('public') |       ->setViewPolicy('public') | ||||||
|       ->setEditPolicy($this->getAuthorPHID()) |       ->setEditPolicy($this->getAuthorPHID()) | ||||||
|       ->setContentSource($content_source) |       ->setContentSource($content_source) | ||||||
|       ->setCommentVersion(1); |       ->setCommentVersion(1); | ||||||
|  |  | ||||||
|     return $this->proxy; |     return $this->getStorageObject(); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function loadID($id) { |  | ||||||
|     $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( |  | ||||||
|       'id = %d', |  | ||||||
|       $id); |  | ||||||
|     if (!$inlines) { |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return head(self::buildProxies($inlines)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function loadPHID($phid) { |  | ||||||
|     $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( |  | ||||||
|       'phid = %s', |  | ||||||
|       $phid); |  | ||||||
|     if (!$inlines) { |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
|     return head(self::buildProxies($inlines)); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function loadDraftComments( |  | ||||||
|     PhabricatorUser $viewer, |  | ||||||
|     $commit_phid, |  | ||||||
|     $raw = false) { |  | ||||||
|  |  | ||||||
|     $inlines = id(new DiffusionDiffInlineCommentQuery()) |  | ||||||
|       ->setViewer($viewer) |  | ||||||
|       ->withAuthorPHIDs(array($viewer->getPHID())) |  | ||||||
|       ->withCommitPHIDs(array($commit_phid)) |  | ||||||
|       ->withHasTransaction(false) |  | ||||||
|       ->withHasPath(true) |  | ||||||
|       ->withIsDeleted(false) |  | ||||||
|       ->needReplyToComments(true) |  | ||||||
|       ->execute(); |  | ||||||
|  |  | ||||||
|     if ($raw) { |  | ||||||
|       return $inlines; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return self::buildProxies($inlines); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function loadPublishedComments( |  | ||||||
|     PhabricatorUser $viewer, |  | ||||||
|     $commit_phid) { |  | ||||||
|  |  | ||||||
|     $inlines = id(new DiffusionDiffInlineCommentQuery()) |  | ||||||
|       ->setViewer($viewer) |  | ||||||
|       ->withCommitPHIDs(array($commit_phid)) |  | ||||||
|       ->withHasTransaction(true) |  | ||||||
|       ->withHasPath(true) |  | ||||||
|       ->execute(); |  | ||||||
|  |  | ||||||
|     return self::buildProxies($inlines); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function loadDraftAndPublishedComments( |  | ||||||
|     PhabricatorUser $viewer, |  | ||||||
|     $commit_phid, |  | ||||||
|     $path_id = null) { |  | ||||||
|  |  | ||||||
|     if ($path_id === null) { |  | ||||||
|       $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( |  | ||||||
|         'commitPHID = %s AND (transactionPHID IS NOT NULL OR authorPHID = %s) |  | ||||||
|           AND pathID IS NOT NULL', |  | ||||||
|         $commit_phid, |  | ||||||
|         $viewer->getPHID()); |  | ||||||
|     } else { |  | ||||||
|       $inlines = id(new PhabricatorAuditTransactionComment())->loadAllWhere( |  | ||||||
|         'commitPHID = %s AND pathID = %d AND |  | ||||||
|           ((authorPHID = %s AND isDeleted = 0) OR transactionPHID IS NOT NULL)', |  | ||||||
|         $commit_phid, |  | ||||||
|         $path_id, |  | ||||||
|         $viewer->getPHID()); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return self::buildProxies($inlines); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   private static function buildProxies(array $inlines) { |  | ||||||
|     $results = array(); |  | ||||||
|     foreach ($inlines as $key => $inline) { |  | ||||||
|       $results[$key] = self::newFromModernComment( |  | ||||||
|         $inline); |  | ||||||
|     } |  | ||||||
|     return $results; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setSyntheticAuthor($synthetic_author) { |  | ||||||
|     $this->syntheticAuthor = $synthetic_author; |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getSyntheticAuthor() { |  | ||||||
|     return $this->syntheticAuthor; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function openTransaction() { |  | ||||||
|     $this->proxy->openTransaction(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function saveTransaction() { |  | ||||||
|     $this->proxy->saveTransaction(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function save() { |  | ||||||
|     $this->getTransactionCommentForSave()->save(); |  | ||||||
|  |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function delete() { |  | ||||||
|     $this->proxy->delete(); |  | ||||||
|  |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getID() { |  | ||||||
|     return $this->proxy->getID(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getPHID() { |  | ||||||
|     return $this->proxy->getPHID(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public static function newFromModernComment( |   public static function newFromModernComment( | ||||||
|     PhabricatorAuditTransactionComment $comment) { |     PhabricatorAuditTransactionComment $comment) { | ||||||
|  |  | ||||||
|     $obj = new PhabricatorAuditInlineComment(); |     $obj = new PhabricatorAuditInlineComment(); | ||||||
|     $obj->proxy = $comment; |     $obj->setStorageObject($comment); | ||||||
|  |  | ||||||
|     return $obj; |     return $obj; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function isCompatible(PhabricatorInlineCommentInterface $comment) { |  | ||||||
|     return |  | ||||||
|       ($this->getAuthorPHID() === $comment->getAuthorPHID()) && |  | ||||||
|       ($this->getSyntheticAuthor() === $comment->getSyntheticAuthor()) && |  | ||||||
|       ($this->getContent() === $comment->getContent()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setContent($content) { |  | ||||||
|     $this->proxy->setContent($content); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getContent() { |  | ||||||
|     return $this->proxy->getContent(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function isDraft() { |  | ||||||
|     return !$this->proxy->getTransactionPHID(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setPathID($id) { |   public function setPathID($id) { | ||||||
|     $this->proxy->setPathID($id); |     $this->getStorageObject()->setPathID($id); | ||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getPathID() { |   public function getPathID() { | ||||||
|     return $this->proxy->getPathID(); |     return $this->getStorageObject()->getPathID(); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setIsNewFile($is_new) { |  | ||||||
|     $this->proxy->setIsNewFile($is_new); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getIsNewFile() { |  | ||||||
|     return $this->proxy->getIsNewFile(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setLineNumber($number) { |  | ||||||
|     $this->proxy->setLineNumber($number); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getLineNumber() { |  | ||||||
|     return $this->proxy->getLineNumber(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setLineLength($length) { |  | ||||||
|     $this->proxy->setLineLength($length); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getLineLength() { |  | ||||||
|     return $this->proxy->getLineLength(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setCache($cache) { |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getCache() { |  | ||||||
|     return null; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setAuthorPHID($phid) { |  | ||||||
|     $this->proxy->setAuthorPHID($phid); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getAuthorPHID() { |  | ||||||
|     return $this->proxy->getAuthorPHID(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function setCommitPHID($commit_phid) { |   public function setCommitPHID($commit_phid) { | ||||||
|     $this->proxy->setCommitPHID($commit_phid); |     $this->getStorageObject()->setCommitPHID($commit_phid); | ||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getCommitPHID() { |   public function getCommitPHID() { | ||||||
|     return $this->proxy->getCommitPHID(); |     return $this->getStorageObject()->getCommitPHID(); | ||||||
|   } |  | ||||||
|  |  | ||||||
|   // When setting a comment ID, we also generate a phantom transaction PHID for |  | ||||||
|   // the future transaction. |  | ||||||
|  |  | ||||||
|   public function setAuditCommentID($id) { |  | ||||||
|     $this->proxy->setLegacyCommentID($id); |  | ||||||
|     $this->proxy->setTransactionPHID( |  | ||||||
|       PhabricatorPHID::generateNewPHID( |  | ||||||
|         PhabricatorApplicationTransactionTransactionPHIDType::TYPECONST, |  | ||||||
|         PhabricatorRepositoryCommitPHIDType::TYPECONST)); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getAuditCommentID() { |  | ||||||
|     return $this->proxy->getLegacyCommentID(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function setChangesetID($id) { |   public function setChangesetID($id) { | ||||||
| @@ -286,82 +69,4 @@ final class PhabricatorAuditInlineComment | |||||||
|     return $this->getPathID(); |     return $this->getPathID(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function setReplyToCommentPHID($phid) { |  | ||||||
|     $this->proxy->setReplyToCommentPHID($phid); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getReplyToCommentPHID() { |  | ||||||
|     return $this->proxy->getReplyToCommentPHID(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setHasReplies($has_replies) { |  | ||||||
|     $this->proxy->setHasReplies($has_replies); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getHasReplies() { |  | ||||||
|     return $this->proxy->getHasReplies(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setIsDeleted($is_deleted) { |  | ||||||
|     $this->proxy->setIsDeleted($is_deleted); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getIsDeleted() { |  | ||||||
|     return $this->proxy->getIsDeleted(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setFixedState($state) { |  | ||||||
|     $this->proxy->setFixedState($state); |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getFixedState() { |  | ||||||
|     return $this->proxy->getFixedState(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function setIsGhost($is_ghost) { |  | ||||||
|     $this->isGhost = $is_ghost; |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getIsGhost() { |  | ||||||
|     return $this->isGhost; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getDateModified() { |  | ||||||
|     return $this->proxy->getDateModified(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getDateCreated() { |  | ||||||
|     return $this->proxy->getDateCreated(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| /* -(  PhabricatorMarkupInterface Implementation  )-------------------------- */ |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   public function getMarkupFieldKey($field) { |  | ||||||
|     return 'AI:'.$this->getID(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function newMarkupEngine($field) { |  | ||||||
|     return PhabricatorMarkupEngine::newDifferentialMarkupEngine(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function getMarkupText($field) { |  | ||||||
|     return $this->getContent(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function didMarkupText($field, $output, PhutilMarkupEngine $engine) { |  | ||||||
|     return $output; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function shouldUseMarkupCache($field) { |  | ||||||
|     // Only cache submitted comments. |  | ||||||
|     return ($this->getID() && $this->getAuditCommentID()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,7 +1,9 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
| final class PhabricatorAuditTransactionComment | final class PhabricatorAuditTransactionComment | ||||||
|   extends PhabricatorApplicationTransactionComment { |   extends PhabricatorApplicationTransactionComment | ||||||
|  |   implements | ||||||
|  |     PhabricatorInlineCommentInterface { | ||||||
|  |  | ||||||
|   protected $commitPHID; |   protected $commitPHID; | ||||||
|   protected $pathID; |   protected $pathID; | ||||||
| @@ -12,8 +14,10 @@ final class PhabricatorAuditTransactionComment | |||||||
|   protected $hasReplies = 0; |   protected $hasReplies = 0; | ||||||
|   protected $replyToCommentPHID; |   protected $replyToCommentPHID; | ||||||
|   protected $legacyCommentID; |   protected $legacyCommentID; | ||||||
|  |   protected $attributes = array(); | ||||||
|  |  | ||||||
|   private $replyToComment = self::ATTACHABLE; |   private $replyToComment = self::ATTACHABLE; | ||||||
|  |   private $inlineContext = self::ATTACHABLE; | ||||||
|  |  | ||||||
|   public function getApplicationTransactionObject() { |   public function getApplicationTransactionObject() { | ||||||
|     return new PhabricatorAuditTransaction(); |     return new PhabricatorAuditTransaction(); | ||||||
| @@ -54,6 +58,10 @@ final class PhabricatorAuditTransactionComment | |||||||
|       ), |       ), | ||||||
|     ) + $config[self::CONFIG_KEY_SCHEMA]; |     ) + $config[self::CONFIG_KEY_SCHEMA]; | ||||||
|  |  | ||||||
|  |     $config[self::CONFIG_SERIALIZATION] = array( | ||||||
|  |       'attributes' => self::SERIALIZATION_JSON, | ||||||
|  |     ) + idx($config, self::CONFIG_SERIALIZATION, array()); | ||||||
|  |  | ||||||
|     return $config; |     return $config; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -67,4 +75,27 @@ final class PhabricatorAuditTransactionComment | |||||||
|     return $this->assertAttached($this->replyToComment); |     return $this->assertAttached($this->replyToComment); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function getAttribute($key, $default = null) { | ||||||
|  |     return idx($this->attributes, $key, $default); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function setAttribute($key, $value) { | ||||||
|  |     $this->attributes[$key] = $value; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function newInlineCommentObject() { | ||||||
|  |     return PhabricatorAuditInlineComment::newFromModernComment($this); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getInlineContext() { | ||||||
|  |     return $this->assertAttached($this->inlineContext); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function attachInlineContext( | ||||||
|  |     PhabricatorInlineCommentContext $context = null) { | ||||||
|  |     $this->inlineContext = $context; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Abstract interface to an identity provider or authentication source, like |  * Abstract interface to an identity provider or authentication source, like | ||||||
|  * Twitter, Facebook or Google. |  * Twitter, Facebook, or Google. | ||||||
|  * |  * | ||||||
|  * Generally, adapters are handed some set of credentials particular to the |  * Generally, adapters are handed some set of credentials particular to the | ||||||
|  * provider they adapt, and they turn those credentials into standard |  * provider they adapt, and they turn those credentials into standard | ||||||
| @@ -17,13 +17,37 @@ | |||||||
|  */ |  */ | ||||||
| abstract class PhutilAuthAdapter extends Phobject { | abstract class PhutilAuthAdapter extends Phobject { | ||||||
|  |  | ||||||
|  |   final public function getAccountIdentifiers() { | ||||||
|  |     $result = $this->newAccountIdentifiers(); | ||||||
|  |     assert_instances_of($result, 'PhabricatorExternalAccountIdentifier'); | ||||||
|  |     return $result; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function newAccountIdentifiers() { | ||||||
|  |     $identifiers = array(); | ||||||
|  |  | ||||||
|  |     $raw_identifier = $this->getAccountID(); | ||||||
|  |     if ($raw_identifier !== null) { | ||||||
|  |       $identifiers[] = $this->newAccountIdentifier($raw_identifier); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $identifiers; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   final protected function newAccountIdentifier($raw_identifier) { | ||||||
|  |     return id(new PhabricatorExternalAccountIdentifier()) | ||||||
|  |       ->setIdentifierRaw($raw_identifier); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Get a unique identifier associated with the identity. For most providers, |    * Get a unique identifier associated with the account. | ||||||
|    * this is an account ID. |  | ||||||
|    * |    * | ||||||
|    * The account ID needs to be unique within this adapter's configuration, such |    * This identifier should be permanent, immutable, and uniquely identify | ||||||
|    * that `<adapterKey, accountID>` is globally unique and always identifies the |    * the account. If possible, it should be nonsensitive. For providers that | ||||||
|    * same identity. |    * have a GUID or PHID value for accounts, these are the best values to use. | ||||||
|  |    * | ||||||
|  |    * You can implement @{method:newAccountIdentifiers} instead if a provider | ||||||
|  |    * is unable to emit identifiers with all of these properties. | ||||||
|    * |    * | ||||||
|    * If the adapter was unable to authenticate an identity, it should return |    * If the adapter was unable to authenticate an identity, it should return | ||||||
|    * `null`. |    * `null`. | ||||||
| @@ -31,7 +55,9 @@ abstract class PhutilAuthAdapter extends Phobject { | |||||||
|    * @return string|null Unique account identifier, or `null` if authentication |    * @return string|null Unique account identifier, or `null` if authentication | ||||||
|    *                     failed. |    *                     failed. | ||||||
|    */ |    */ | ||||||
|   abstract public function getAccountID(); |   public function getAccountID() { | ||||||
|  |     throw new PhutilMethodNotImplementedException(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|   | |||||||
| @@ -51,13 +51,17 @@ final class PhutilGitHubAuthAdapter extends PhutilOAuthAuthAdapter { | |||||||
|  |  | ||||||
|   protected function loadOAuthAccountData() { |   protected function loadOAuthAccountData() { | ||||||
|     $uri = new PhutilURI('https://api.github.com/user'); |     $uri = new PhutilURI('https://api.github.com/user'); | ||||||
|     $uri->replaceQueryParam('access_token', $this->getAccessToken()); |  | ||||||
|  |  | ||||||
|     $future = new HTTPSFuture($uri); |     $future = new HTTPSFuture($uri); | ||||||
|  |  | ||||||
|     // NOTE: GitHub requires a User-Agent string. |     // NOTE: GitHub requires a User-Agent string. | ||||||
|     $future->addHeader('User-Agent', __CLASS__); |     $future->addHeader('User-Agent', __CLASS__); | ||||||
|  |  | ||||||
|  |     // See T13485. Circa early 2020, GitHub has deprecated use of the | ||||||
|  |     // "access_token" URI parameter. | ||||||
|  |     $token_header = sprintf('token %s', $this->getAccessToken()); | ||||||
|  |     $future->addHeader('Authorization', $token_header); | ||||||
|  |  | ||||||
|     list($body) = $future->resolvex(); |     list($body) = $future->resolvex(); | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|   | |||||||
| @@ -13,8 +13,23 @@ final class PhutilGoogleAuthAdapter extends PhutilOAuthAuthAdapter { | |||||||
|     return 'google.com'; |     return 'google.com'; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getAccountID() { |   protected function newAccountIdentifiers() { | ||||||
|     return $this->getAccountEmail(); |     $identifiers = array(); | ||||||
|  |  | ||||||
|  |     $account_id = $this->getOAuthAccountData('id'); | ||||||
|  |     if ($account_id !== null) { | ||||||
|  |       $account_id = sprintf( | ||||||
|  |         'id(%s)', | ||||||
|  |         $account_id); | ||||||
|  |       $identifiers[] = $this->newAccountIdentifier($account_id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $email = $this->getAccountEmail(); | ||||||
|  |     if ($email !== null) { | ||||||
|  |       $identifiers[] = $this->newAccountIdentifier($email); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $identifiers; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getAccountEmail() { |   public function getAccountEmail() { | ||||||
|   | |||||||
| @@ -10,7 +10,6 @@ final class PhutilJIRAAuthAdapter extends PhutilOAuth1AuthAdapter { | |||||||
|  |  | ||||||
|   private $jiraBaseURI; |   private $jiraBaseURI; | ||||||
|   private $adapterDomain; |   private $adapterDomain; | ||||||
|   private $currentSession; |  | ||||||
|   private $userInfo; |   private $userInfo; | ||||||
|  |  | ||||||
|   public function setJIRABaseURI($jira_base_uri) { |   public function setJIRABaseURI($jira_base_uri) { | ||||||
| @@ -22,12 +21,33 @@ final class PhutilJIRAAuthAdapter extends PhutilOAuth1AuthAdapter { | |||||||
|     return $this->jiraBaseURI; |     return $this->jiraBaseURI; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getAccountID() { |   protected function newAccountIdentifiers() { | ||||||
|     // Make sure the handshake is finished; this method is used for its |     // Make sure the handshake is finished; this method is used for its | ||||||
|     // side effect by Auth providers. |     // side effect by Auth providers. | ||||||
|     $this->getHandshakeData(); |     $this->getHandshakeData(); | ||||||
|  |  | ||||||
|     return idx($this->getUserInfo(), 'key'); |     $info = $this->getUserInfo(); | ||||||
|  |  | ||||||
|  |     // See T13493. Older versions of JIRA provide a "key" with a username or | ||||||
|  |     // email address. Newer versions of JIRA provide a GUID "accountId". | ||||||
|  |     // Intermediate versions of JIRA provide both. | ||||||
|  |  | ||||||
|  |     $identifiers = array(); | ||||||
|  |  | ||||||
|  |     $account_key = idx($info, 'key'); | ||||||
|  |     if ($account_key !== null) { | ||||||
|  |       $identifiers[] = $this->newAccountIdentifier($account_key); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $account_id = idx($info, 'accountId'); | ||||||
|  |     if ($account_id !== null) { | ||||||
|  |       $identifiers[] = $this->newAccountIdentifier( | ||||||
|  |         sprintf( | ||||||
|  |           'accountId(%s)', | ||||||
|  |           $account_id)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $identifiers; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getAccountName() { |   public function getAccountName() { | ||||||
| @@ -85,23 +105,36 @@ final class PhutilJIRAAuthAdapter extends PhutilOAuth1AuthAdapter { | |||||||
|  |  | ||||||
|   private function getUserInfo() { |   private function getUserInfo() { | ||||||
|     if ($this->userInfo === null) { |     if ($this->userInfo === null) { | ||||||
|       $this->currentSession = $this->newJIRAFuture('rest/auth/1/session', 'GET') |       $this->userInfo = $this->newUserInfo(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->userInfo; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function newUserInfo() { | ||||||
|  |     // See T13493. Try a relatively modern (circa early 2020) API call first. | ||||||
|  |     try { | ||||||
|  |       return $this->newJIRAFuture('rest/api/3/myself', 'GET') | ||||||
|  |         ->resolveJSON(); | ||||||
|  |     } catch (Exception $ex) { | ||||||
|  |       // If we failed the v3 call, assume the server version is too old | ||||||
|  |       // to support this API and fall back to trying the older method. | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $session = $this->newJIRAFuture('rest/auth/1/session', 'GET') | ||||||
|       ->resolveJSON(); |       ->resolveJSON(); | ||||||
|  |  | ||||||
|     // The session call gives us the username, but not the user key or other |     // The session call gives us the username, but not the user key or other | ||||||
|     // information. Make a second call to get additional information. |     // information. Make a second call to get additional information. | ||||||
|  |  | ||||||
|     $params = array( |     $params = array( | ||||||
|         'username' => $this->currentSession['name'], |       'username' => $session['name'], | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|       $this->userInfo = $this->newJIRAFuture('rest/api/2/user', 'GET', $params) |     return $this->newJIRAFuture('rest/api/2/user', 'GET', $params) | ||||||
|       ->resolveJSON(); |       ->resolveJSON(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|     return $this->userInfo; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function newJIRAKeypair() { |   public static function newJIRAKeypair() { | ||||||
|     $config = array( |     $config = array( | ||||||
|       'digest_alg' => 'sha512', |       'digest_alg' => 'sha512', | ||||||
|   | |||||||
| @@ -156,7 +156,7 @@ abstract class PhutilOAuth1AuthAdapter extends PhutilAuthAdapter { | |||||||
|     $authorize_token_uri = new PhutilURI($this->getAuthorizeTokenURI()); |     $authorize_token_uri = new PhutilURI($this->getAuthorizeTokenURI()); | ||||||
|     $authorize_token_uri->replaceQueryParam('oauth_token', $this->getToken()); |     $authorize_token_uri->replaceQueryParam('oauth_token', $this->getToken()); | ||||||
|  |  | ||||||
|     return (string)$authorize_token_uri; |     return phutil_string_cast($authorize_token_uri); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected function finishOAuthHandshake() { |   protected function finishOAuthHandshake() { | ||||||
|   | |||||||
| @@ -73,7 +73,7 @@ final class PhabricatorAuthApplication extends PhabricatorApplication { | |||||||
|         'session/downgrade/' |         'session/downgrade/' | ||||||
|           => 'PhabricatorAuthDowngradeSessionController', |           => 'PhabricatorAuthDowngradeSessionController', | ||||||
|         'enroll/' => array( |         'enroll/' => array( | ||||||
|           '(?:(?P<pageKey>[^/]+)/)?(?:(?P<formSaved>saved)/)?' |           '(?:(?P<pageKey>[^/]+)/)?' | ||||||
|             => 'PhabricatorAuthNeedsMultiFactorController', |             => 'PhabricatorAuthNeedsMultiFactorController', | ||||||
|         ), |         ), | ||||||
|         'sshkey/' => array( |         'sshkey/' => array( | ||||||
|   | |||||||
| @@ -63,6 +63,13 @@ final class PhabricatorCookies extends Phobject { | |||||||
|   const COOKIE_INVITE = 'invite'; |   const COOKIE_INVITE = 'invite'; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   /** | ||||||
|  |    * Stores a workflow completion across a redirect-after-POST following a | ||||||
|  |    * form submission. This can be used to show "Changes Saved" messages. | ||||||
|  |    */ | ||||||
|  |   const COOKIE_SUBMIT = 'phfrm'; | ||||||
|  |  | ||||||
|  |  | ||||||
| /* -(  Client ID Cookie  )--------------------------------------------------- */ | /* -(  Client ID Cookie  )--------------------------------------------------- */ | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -197,22 +197,6 @@ abstract class PhabricatorAuthController extends PhabricatorController { | |||||||
|       return array($account, $provider, $response); |       return array($account, $provider, $response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $other_account = id(new PhabricatorExternalAccount())->loadAllWhere( |  | ||||||
|       'accountType = %s AND accountDomain = %s AND accountID = %s |  | ||||||
|         AND id != %d', |  | ||||||
|       $account->getAccountType(), |  | ||||||
|       $account->getAccountDomain(), |  | ||||||
|       $account->getAccountID(), |  | ||||||
|       $account->getID()); |  | ||||||
|  |  | ||||||
|     if ($other_account) { |  | ||||||
|       $response = $this->renderError( |  | ||||||
|         pht( |  | ||||||
|           'The account you are attempting to register with already belongs '. |  | ||||||
|           'to another user.')); |  | ||||||
|       return array($account, $provider, $response); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $config = $account->getProviderConfig(); |     $config = $account->getProviderConfig(); | ||||||
|     if (!$config->getIsEnabled()) { |     if (!$config->getIsEnabled()) { | ||||||
|       $response = $this->renderError( |       $response = $this->renderError( | ||||||
|   | |||||||
| @@ -116,14 +116,21 @@ final class PhabricatorAuthLoginController | |||||||
|         } |         } | ||||||
|       } else { |       } else { | ||||||
|  |  | ||||||
|         // If the user already has a linked account of this type, prevent them |         // If the user already has a linked account on this provider, prevent | ||||||
|         // from linking a second account. This can happen if they swap logins |         // them from linking a second account. This can happen if they swap | ||||||
|         // and then refresh the account link. See T6707. We will eventually |         // logins and then refresh the account link. | ||||||
|         // allow this after T2549. |  | ||||||
|  |         // There's no technical reason we can't allow you to link multiple | ||||||
|  |         // accounts from a single provider; disallowing this is currently a | ||||||
|  |         // product deciison. See T2549. | ||||||
|  |  | ||||||
|         $existing_accounts = id(new PhabricatorExternalAccountQuery()) |         $existing_accounts = id(new PhabricatorExternalAccountQuery()) | ||||||
|           ->setViewer($viewer) |           ->setViewer($viewer) | ||||||
|           ->withUserPHIDs(array($viewer->getPHID())) |           ->withUserPHIDs(array($viewer->getPHID())) | ||||||
|           ->withAccountTypes(array($account->getAccountType())) |           ->withProviderConfigPHIDs( | ||||||
|  |             array( | ||||||
|  |               $provider->getProviderConfigPHID(), | ||||||
|  |             )) | ||||||
|           ->execute(); |           ->execute(); | ||||||
|         if ($existing_accounts) { |         if ($existing_accounts) { | ||||||
|           return $this->renderError( |           return $this->renderError( | ||||||
|   | |||||||
| @@ -346,6 +346,14 @@ final class PhabricatorAuthRegisterController | |||||||
|         } |         } | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  |       // blender hack | ||||||
|  |       $root = dirname(phutil_get_library_root('phabricator')); | ||||||
|  |       require $root.'/migration/dedup.php'; | ||||||
|  |       if (array_key_exists($request->getStr('username'), $migrate_dedup_users)) { | ||||||
|  |         $e_username = pht('Duplicate'); | ||||||
|  |         $errors[] = pht('Username is already reserved.'); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       if (!$errors) { |       if (!$errors) { | ||||||
|         if (!$is_setup) { |         if (!$is_setup) { | ||||||
|           $image = $this->loadProfilePicture($account); |           $image = $this->loadProfilePicture($account); | ||||||
| @@ -457,7 +465,6 @@ final class PhabricatorAuthRegisterController | |||||||
|  |  | ||||||
|             if (!$is_setup) { |             if (!$is_setup) { | ||||||
|               $account->setUserPHID($user->getPHID()); |               $account->setUserPHID($user->getPHID()); | ||||||
|               $provider->willRegisterAccount($account); |  | ||||||
|               $account->save(); |               $account->save(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -67,7 +67,7 @@ final class PhabricatorAuthUnlinkController | |||||||
|       ->setWorkflowKey($workflow_key) |       ->setWorkflowKey($workflow_key) | ||||||
|       ->requireHighSecurityToken($viewer, $request, $done_uri); |       ->requireHighSecurityToken($viewer, $request, $done_uri); | ||||||
|  |  | ||||||
|     $account->delete(); |     $account->unlinkAccount(); | ||||||
|  |  | ||||||
|     id(new PhabricatorAuthSessionEngine())->terminateLoginSessions( |     id(new PhabricatorAuthSessionEngine())->terminateLoginSessions( | ||||||
|       $viewer, |       $viewer, | ||||||
|   | |||||||
| @@ -56,9 +56,12 @@ final class PhabricatorAuthManagementLDAPWorkflow | |||||||
|     $console->writeOut("\n"); |     $console->writeOut("\n"); | ||||||
|     $console->writeOut("%s\n", pht('Connecting to LDAP...')); |     $console->writeOut("%s\n", pht('Connecting to LDAP...')); | ||||||
|  |  | ||||||
|     $account_id = $adapter->getAccountID(); |     $account_ids = $adapter->getAccountIdentifiers(); | ||||||
|     if ($account_id) { |     if ($account_ids) { | ||||||
|       $console->writeOut("%s\n", pht('Found LDAP Account: %s', $account_id)); |       $value_list = mpull($account_ids, 'getIdentifierRaw'); | ||||||
|  |       $value_list = implode(', ', $value_list); | ||||||
|  |  | ||||||
|  |       $console->writeOut("%s\n", pht('Found LDAP Account: %s', $value_list)); | ||||||
|     } else { |     } else { | ||||||
|       $console->writeOut("%s\n", pht('Unable to find LDAP account!')); |       $console->writeOut("%s\n", pht('Unable to find LDAP account!')); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -18,16 +18,6 @@ final class PhabricatorAuthManagementRefreshWorkflow | |||||||
|             'param' => 'user', |             'param' => 'user', | ||||||
|             'help' => pht('Refresh tokens for a given user.'), |             'help' => pht('Refresh tokens for a given user.'), | ||||||
|           ), |           ), | ||||||
|           array( |  | ||||||
|             'name' => 'type', |  | ||||||
|             'param' => 'provider', |  | ||||||
|             'help' => pht('Refresh tokens for a given provider type.'), |  | ||||||
|           ), |  | ||||||
|           array( |  | ||||||
|             'name' => 'domain', |  | ||||||
|             'param' => 'domain', |  | ||||||
|             'help' => pht('Refresh tokens for a given domain.'), |  | ||||||
|           ), |  | ||||||
|         )); |         )); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -57,17 +47,6 @@ final class PhabricatorAuthManagementRefreshWorkflow | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|     $type = $args->getArg('type'); |  | ||||||
|     if (strlen($type)) { |  | ||||||
|       $query->withAccountTypes(array($type)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $domain = $args->getArg('domain'); |  | ||||||
|     if (strlen($domain)) { |  | ||||||
|       $query->withAccountDomains(array($domain)); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $accounts = $query->execute(); |     $accounts = $query->execute(); | ||||||
|  |  | ||||||
|     if (!$accounts) { |     if (!$accounts) { | ||||||
| @@ -82,25 +61,24 @@ final class PhabricatorAuthManagementRefreshWorkflow | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     $providers = PhabricatorAuthProvider::getAllEnabledProviders(); |     $providers = PhabricatorAuthProvider::getAllEnabledProviders(); | ||||||
|  |     $providers = mpull($providers, null, 'getProviderConfigPHID'); | ||||||
|  |  | ||||||
|     foreach ($accounts as $account) { |     foreach ($accounts as $account) { | ||||||
|       $console->writeOut( |       $console->writeOut( | ||||||
|         "%s\n", |         "%s\n", | ||||||
|         pht( |         pht( | ||||||
|           'Refreshing account #%d (%s/%s).', |           'Refreshing account #%d.', | ||||||
|           $account->getID(), |           $account->getID())); | ||||||
|           $account->getAccountType(), |  | ||||||
|           $account->getAccountDomain())); |  | ||||||
|  |  | ||||||
|       $key = $account->getProviderKey(); |       $config_phid = $account->getProviderConfigPHID(); | ||||||
|       if (empty($providers[$key])) { |       if (empty($providers[$config_phid])) { | ||||||
|         $console->writeOut( |         $console->writeOut( | ||||||
|           "> %s\n", |           "> %s\n", | ||||||
|           pht('Skipping, provider is not enabled or does not exist.')); |           pht('Skipping, provider is not enabled or does not exist.')); | ||||||
|         continue; |         continue; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       $provider = $providers[$key]; |       $provider = $providers[$config_phid]; | ||||||
|       if (!($provider instanceof PhabricatorOAuth2AuthProvider)) { |       if (!($provider instanceof PhabricatorOAuth2AuthProvider)) { | ||||||
|         $console->writeOut( |         $console->writeOut( | ||||||
|           "> %s\n", |           "> %s\n", | ||||||
|   | |||||||
| @@ -20,6 +20,10 @@ abstract class PhabricatorAuthProvider extends Phobject { | |||||||
|     return $this->providerConfig; |     return $this->providerConfig; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function getProviderConfigPHID() { | ||||||
|  |     return $this->getProviderConfig()->getPHID(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public function getConfigurationHelp() { |   public function getConfigurationHelp() { | ||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
| @@ -186,44 +190,86 @@ abstract class PhabricatorAuthProvider extends Phobject { | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function willRegisterAccount(PhabricatorExternalAccount $account) { |   final protected function newExternalAccountForIdentifiers( | ||||||
|     return; |     array $identifiers) { | ||||||
|   } |  | ||||||
|  |  | ||||||
|   protected function loadOrCreateAccount($account_id) { |     assert_instances_of($identifiers, 'PhabricatorExternalAccountIdentifier'); | ||||||
|     if (!strlen($account_id)) { |  | ||||||
|       throw new Exception(pht('Empty account ID!')); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     $adapter = $this->getAdapter(); |     if (!$identifiers) { | ||||||
|     $adapter_class = get_class($adapter); |  | ||||||
|  |  | ||||||
|     if (!strlen($adapter->getAdapterType())) { |  | ||||||
|       throw new Exception( |       throw new Exception( | ||||||
|         pht( |         pht( | ||||||
|           "AuthAdapter (of class '%s') has an invalid implementation: ". |           'Authentication provider (of class "%s") is attempting to '. | ||||||
|           "no adapter type.", |           'load or create an external account, but provided no account '. | ||||||
|           $adapter_class)); |           'identifiers.', | ||||||
|  |           get_class($this))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!strlen($adapter->getAdapterDomain())) { |     $config = $this->getProviderConfig(); | ||||||
|  |     $viewer = PhabricatorUser::getOmnipotentUser(); | ||||||
|  |  | ||||||
|  |     $raw_identifiers = mpull($identifiers, 'getIdentifierRaw'); | ||||||
|  |  | ||||||
|  |     $accounts = id(new PhabricatorExternalAccountQuery()) | ||||||
|  |       ->setViewer($viewer) | ||||||
|  |       ->withProviderConfigPHIDs(array($config->getPHID())) | ||||||
|  |       ->withRawAccountIdentifiers($raw_identifiers) | ||||||
|  |       ->needAccountIdentifiers(true) | ||||||
|  |       ->execute(); | ||||||
|  |     if (!$accounts) { | ||||||
|  |       $account = $this->newExternalAccount(); | ||||||
|  |     } else if (count($accounts) === 1) { | ||||||
|  |       $account = head($accounts); | ||||||
|  |     } else { | ||||||
|       throw new Exception( |       throw new Exception( | ||||||
|         pht( |         pht( | ||||||
|           "AuthAdapter (of class '%s') has an invalid implementation: ". |           'Authentication provider (of class "%s") is attempting to load '. | ||||||
|           "no adapter domain.", |           'or create an external account, but provided a list of '. | ||||||
|           $adapter_class)); |           'account identifiers which map to more than one account: %s.', | ||||||
|  |           get_class($this), | ||||||
|  |           implode(', ', $raw_identifiers))); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $account = id(new PhabricatorExternalAccount())->loadOneWhere( |     // See T13493. Add all the identifiers to the account. In the case where | ||||||
|       'accountType = %s AND accountDomain = %s AND accountID = %s', |     // an account initially has a lower-quality identifier (like an email | ||||||
|       $adapter->getAdapterType(), |     // address) and later adds a higher-quality identifier (like a GUID), this | ||||||
|       $adapter->getAdapterDomain(), |     // allows us to automatically upgrade toward the higher-quality identifier | ||||||
|       $account_id); |     // and survive API changes which remove the lower-quality identifier more | ||||||
|  |     // gracefully. | ||||||
|  |  | ||||||
|  |     foreach ($identifiers as $identifier) { | ||||||
|  |       $account->appendIdentifier($identifier); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $this->didUpdateAccount($account); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   final protected function newExternalAccountForUser(PhabricatorUser $user) { | ||||||
|  |     $config = $this->getProviderConfig(); | ||||||
|  |  | ||||||
|  |     // When a user logs in with a provider like username/password, they | ||||||
|  |     // always already have a Phabricator account (since there's no way they | ||||||
|  |     // could have a username otherwise). | ||||||
|  |  | ||||||
|  |     // These users should never go to registration, so we're building a | ||||||
|  |     // dummy "external account" which just links directly back to their | ||||||
|  |     // internal account. | ||||||
|  |  | ||||||
|  |     $account = id(new PhabricatorExternalAccountQuery()) | ||||||
|  |       ->setViewer($user) | ||||||
|  |       ->withProviderConfigPHIDs(array($config->getPHID())) | ||||||
|  |       ->withUserPHIDs(array($user->getPHID())) | ||||||
|  |       ->executeOne(); | ||||||
|     if (!$account) { |     if (!$account) { | ||||||
|       $account = $this->newExternalAccount() |       $account = $this->newExternalAccount() | ||||||
|         ->setAccountID($account_id); |         ->setUserPHID($user->getPHID()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     return $this->didUpdateAccount($account); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   private function didUpdateAccount(PhabricatorExternalAccount $account) { | ||||||
|  |     $adapter = $this->getAdapter(); | ||||||
|  |  | ||||||
|     $account->setUsername($adapter->getAccountName()); |     $account->setUsername($adapter->getAccountName()); | ||||||
|     $account->setRealName($adapter->getAccountRealName()); |     $account->setRealName($adapter->getAccountRealName()); | ||||||
|     $account->setEmail($adapter->getAccountEmail()); |     $account->setEmail($adapter->getAccountEmail()); | ||||||
| @@ -240,6 +286,7 @@ abstract class PhabricatorAuthProvider extends Phobject { | |||||||
|         // file entry for it, but there's no convenient way to do this with |         // file entry for it, but there's no convenient way to do this with | ||||||
|         // PhabricatorFile right now. The storage will get shared, so the impact |         // PhabricatorFile right now. The storage will get shared, so the impact | ||||||
|         // here is negligible. |         // here is negligible. | ||||||
|  |  | ||||||
|         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); |         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); | ||||||
|           $image_file = PhabricatorFile::newFromFileDownload( |           $image_file = PhabricatorFile::newFromFileDownload( | ||||||
|             $image_uri, |             $image_uri, | ||||||
| @@ -305,10 +352,23 @@ abstract class PhabricatorAuthProvider extends Phobject { | |||||||
|     $config = $this->getProviderConfig(); |     $config = $this->getProviderConfig(); | ||||||
|     $adapter = $this->getAdapter(); |     $adapter = $this->getAdapter(); | ||||||
|  |  | ||||||
|     return id(new PhabricatorExternalAccount()) |     $account = id(new PhabricatorExternalAccount()) | ||||||
|  |       ->setProviderConfigPHID($config->getPHID()) | ||||||
|  |       ->attachAccountIdentifiers(array()); | ||||||
|  |  | ||||||
|  |     // TODO: Remove this when these columns are removed. They no longer have | ||||||
|  |     // readers or writers (other than this callsite). | ||||||
|  |  | ||||||
|  |     $account | ||||||
|       ->setAccountType($adapter->getAdapterType()) |       ->setAccountType($adapter->getAdapterType()) | ||||||
|       ->setAccountDomain($adapter->getAdapterDomain()) |       ->setAccountDomain($adapter->getAdapterDomain()); | ||||||
|       ->setProviderConfigPHID($config->getPHID()); |  | ||||||
|  |     // TODO: Remove this when "accountID" is removed; the column is not | ||||||
|  |     // nullable. | ||||||
|  |  | ||||||
|  |     $account->setAccountID(''); | ||||||
|  |  | ||||||
|  |     return $account; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function getLoginOrder() { |   public function getLoginOrder() { | ||||||
|   | |||||||
| @@ -335,7 +335,7 @@ final class PhabricatorJIRAAuthProvider | |||||||
|   public function getDoorkeeperURIRef(PhutilURI $uri) { |   public function getDoorkeeperURIRef(PhutilURI $uri) { | ||||||
|     $uri_string = phutil_string_cast($uri); |     $uri_string = phutil_string_cast($uri); | ||||||
|  |  | ||||||
|     $pattern = '((https?://\S+?)/browse/([A-Z]+-[1-9]\d*))'; |     $pattern = '((https?://\S+?)/browse/([A-Z][A-Z0-9]*-[1-9]\d*))'; | ||||||
|     $matches = null; |     $matches = null; | ||||||
|     if (!preg_match($pattern, $uri_string, $matches)) { |     if (!preg_match($pattern, $uri_string, $matches)) { | ||||||
|       return null; |       return null; | ||||||
|   | |||||||
| @@ -164,7 +164,7 @@ final class PhabricatorLDAPAuthProvider extends PhabricatorAuthProvider { | |||||||
|           // See T3351. |           // See T3351. | ||||||
|  |  | ||||||
|           DarkConsoleErrorLogPluginAPI::enableDiscardMode(); |           DarkConsoleErrorLogPluginAPI::enableDiscardMode(); | ||||||
|             $account_id = $adapter->getAccountID(); |             $identifiers = $adapter->getAccountIdentifiers(); | ||||||
|           DarkConsoleErrorLogPluginAPI::disableDiscardMode(); |           DarkConsoleErrorLogPluginAPI::disableDiscardMode(); | ||||||
|         } else { |         } else { | ||||||
|           throw new Exception(pht('Username and password are required!')); |           throw new Exception(pht('Username and password are required!')); | ||||||
| @@ -180,7 +180,9 @@ final class PhabricatorLDAPAuthProvider extends PhabricatorAuthProvider { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return array($this->loadOrCreateAccount($account_id), $response); |     $account = $this->newExternalAccountForIdentifiers($identifiers); | ||||||
|  |  | ||||||
|  |     return array($account, $response); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -100,13 +100,13 @@ abstract class PhabricatorOAuth1AuthProvider | |||||||
|     // an access token. |     // an access token. | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|       $account_id = $adapter->getAccountID(); |       $identifiers = $adapter->getAccountIdentifiers(); | ||||||
|     } catch (Exception $ex) { |     } catch (Exception $ex) { | ||||||
|       // TODO: Handle this in a more user-friendly way. |       // TODO: Handle this in a more user-friendly way. | ||||||
|       throw $ex; |       throw $ex; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!strlen($account_id)) { |     if (!$identifiers) { | ||||||
|       $response = $controller->buildProviderErrorResponse( |       $response = $controller->buildProviderErrorResponse( | ||||||
|         $this, |         $this, | ||||||
|         pht( |         pht( | ||||||
| @@ -115,7 +115,9 @@ abstract class PhabricatorOAuth1AuthProvider | |||||||
|       return array($account, $response); |       return array($account, $response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return array($this->loadOrCreateAccount($account_id), $response); |     $account = $this->newExternalAccountForIdentifiers($identifiers); | ||||||
|  |  | ||||||
|  |     return array($account, $response); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function processEditForm( |   public function processEditForm( | ||||||
|   | |||||||
| @@ -80,13 +80,13 @@ abstract class PhabricatorOAuth2AuthProvider | |||||||
|     // an access token. |     // an access token. | ||||||
|  |  | ||||||
|     try { |     try { | ||||||
|       $account_id = $adapter->getAccountID(); |       $identifiers = $adapter->getAccountIdentifiers(); | ||||||
|     } catch (Exception $ex) { |     } catch (Exception $ex) { | ||||||
|       // TODO: Handle this in a more user-friendly way. |       // TODO: Handle this in a more user-friendly way. | ||||||
|       throw $ex; |       throw $ex; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!strlen($account_id)) { |     if (!$identifiers) { | ||||||
|       $response = $controller->buildProviderErrorResponse( |       $response = $controller->buildProviderErrorResponse( | ||||||
|         $this, |         $this, | ||||||
|         pht( |         pht( | ||||||
| @@ -95,7 +95,9 @@ abstract class PhabricatorOAuth2AuthProvider | |||||||
|       return array($account, $response); |       return array($account, $response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return array($this->loadOrCreateAccount($account_id), $response); |     $account = $this->newExternalAccountForIdentifiers($identifiers); | ||||||
|  |  | ||||||
|  |     return array($account, $response); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function processEditForm( |   public function processEditForm( | ||||||
| @@ -197,7 +199,7 @@ abstract class PhabricatorOAuth2AuthProvider | |||||||
|     PhabricatorExternalAccount $account, |     PhabricatorExternalAccount $account, | ||||||
|     $force_refresh = false) { |     $force_refresh = false) { | ||||||
|  |  | ||||||
|     if ($account->getProviderKey() !== $this->getProviderKey()) { |     if ($account->getProviderConfigPHID() !== $this->getProviderConfigPHID()) { | ||||||
|       throw new Exception(pht('Account does not match provider!')); |       throw new Exception(pht('Account does not match provider!')); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -173,8 +173,8 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|     $dialog = id(new AphrontDialogView()) |     $dialog = id(new AphrontDialogView()) | ||||||
|       ->setSubmitURI($this->getLoginURI()) |       ->setSubmitURI($this->getLoginURI()) | ||||||
|       ->setUser($viewer) |       ->setUser($viewer) | ||||||
|       ->setTitle(pht('Log In')) |       ->setTitle(pht('Login to developer.blender.org')) | ||||||
|       ->addSubmitButton(pht('Log In')); |       ->addSubmitButton(pht('Login')); | ||||||
|  |  | ||||||
|     if ($this->shouldAllowRegistration()) { |     if ($this->shouldAllowRegistration()) { | ||||||
|       $dialog->addCancelButton( |       $dialog->addCancelButton( | ||||||
| @@ -182,6 +182,11 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|         pht('Register New Account')); |         pht('Register New Account')); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     $webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/'; | ||||||
|  |     $dialog->addFooter( | ||||||
|  |       phutil_safe_html( | ||||||
|  |         FileSystem::readFile($webroot .'rsrc/custom/static/login.html'))); | ||||||
|  |  | ||||||
|     $dialog->addFooter( |     $dialog->addFooter( | ||||||
|       phutil_tag( |       phutil_tag( | ||||||
|         'a', |         'a', | ||||||
| @@ -217,6 +222,28 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|       $errors[] = pht('Username or password are incorrect.'); |       $errors[] = pht('Username or password are incorrect.'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (true) { | ||||||
|  |       // blender hack | ||||||
|  |       $root = dirname(phutil_get_library_root('phabricator')); | ||||||
|  |       require $root.'/migration/dedup.php'; | ||||||
|  |  | ||||||
|  |       $missing_username = $request->getStr('username'); | ||||||
|  |  | ||||||
|  |       $find_user = id(new PhabricatorUser())->loadOneWhere( | ||||||
|  |         'username = %s', | ||||||
|  |          $missing_username); | ||||||
|  |  | ||||||
|  |       if (!$find_user && array_key_exists($missing_username, $migrate_dedup_users)) { | ||||||
|  |         $errors = array(); | ||||||
|  |         $errors[] = pht('This account was merged into account "' . | ||||||
|  |                         $migrate_dedup_users[$missing_username] . | ||||||
|  |                         '", because Phabricator does not support multiple accounts with the same email address. ' . | ||||||
|  |                         'Please login with that account instead ' . | ||||||
|  |                         '(optionally recovering your password if you forgot it). ' . | ||||||
|  |                         'After logging in you will be able to change your username in the User Settings.'); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if ($errors) { |     if ($errors) { | ||||||
|       $errors = id(new PHUIInfoView())->setErrors($errors); |       $errors = id(new PHUIInfoView())->setErrors($errors); | ||||||
|     } |     } | ||||||
| @@ -305,7 +332,7 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|               ->setObject($user); |               ->setObject($user); | ||||||
|  |  | ||||||
|             if ($engine->isValidPassword($envelope)) { |             if ($engine->isValidPassword($envelope)) { | ||||||
|               $account = $this->loadOrCreateAccount($user->getPHID()); |               $account = $this->newExternalAccountForUser($user); | ||||||
|               $log_user = $user; |               $log_user = $user; | ||||||
|             } |             } | ||||||
|           } |           } | ||||||
| @@ -339,16 +366,6 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|     return true; |     return true; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected function willSaveAccount(PhabricatorExternalAccount $account) { |  | ||||||
|     parent::willSaveAccount($account); |  | ||||||
|     $account->setUserPHID($account->getAccountID()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function willRegisterAccount(PhabricatorExternalAccount $account) { |  | ||||||
|     parent::willRegisterAccount($account); |  | ||||||
|     $account->setAccountID($account->getUserPHID()); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public static function getPasswordProvider() { |   public static function getPasswordProvider() { | ||||||
|     $providers = self::getAllEnabledProviders(); |     $providers = self::getAllEnabledProviders(); | ||||||
|  |  | ||||||
| @@ -375,4 +392,5 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider { | |||||||
|   public function shouldAllowEmailTrustConfiguration() { |   public function shouldAllowEmailTrustConfiguration() { | ||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,94 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | final class PhabricatorExternalAccountIdentifierQuery | ||||||
|  |   extends PhabricatorCursorPagedPolicyAwareQuery { | ||||||
|  |  | ||||||
|  |   private $ids; | ||||||
|  |   private $phids; | ||||||
|  |   private $providerConfigPHIDs; | ||||||
|  |   private $externalAccountPHIDs; | ||||||
|  |   private $rawIdentifiers; | ||||||
|  |  | ||||||
|  |   public function withIDs($ids) { | ||||||
|  |     $this->ids = $ids; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function withPHIDs(array $phids) { | ||||||
|  |     $this->phids = $phids; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function withProviderConfigPHIDs(array $phids) { | ||||||
|  |     $this->providerConfigPHIDs = $phids; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function withExternalAccountPHIDs(array $phids) { | ||||||
|  |     $this->externalAccountPHIDs = $phids; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function withRawIdentifiers(array $identifiers) { | ||||||
|  |     $this->rawIdentifiers = $identifiers; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function newResultObject() { | ||||||
|  |     return new PhabricatorExternalAccountIdentifier(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   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->providerConfigPHIDs !== null) { | ||||||
|  |       $where[] = qsprintf( | ||||||
|  |         $conn, | ||||||
|  |         'providerConfigPHID IN (%Ls)', | ||||||
|  |         $this->providerConfigPHIDs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($this->externalAccountPHIDs !== null) { | ||||||
|  |       $where[] = qsprintf( | ||||||
|  |         $conn, | ||||||
|  |         'externalAccountPHID IN (%Ls)', | ||||||
|  |         $this->externalAccountPHIDs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($this->rawIdentifiers !== null) { | ||||||
|  |       $hashes = array(); | ||||||
|  |       foreach ($this->rawIdentifiers as $raw_identifier) { | ||||||
|  |         $hashes[] = PhabricatorHash::digestForIndex($raw_identifier); | ||||||
|  |       } | ||||||
|  |       $where[] = qsprintf( | ||||||
|  |         $conn, | ||||||
|  |         'identifierHash IN (%Ls)', | ||||||
|  |         $hashes); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $where; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public function getQueryApplicationClass() { | ||||||
|  |     return 'PhabricatorPeopleApplication'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -15,34 +15,18 @@ final class PhabricatorExternalAccountQuery | |||||||
|  |  | ||||||
|   private $ids; |   private $ids; | ||||||
|   private $phids; |   private $phids; | ||||||
|   private $accountTypes; |  | ||||||
|   private $accountDomains; |  | ||||||
|   private $accountIDs; |  | ||||||
|   private $userPHIDs; |   private $userPHIDs; | ||||||
|   private $needImages; |   private $needImages; | ||||||
|   private $accountSecrets; |   private $accountSecrets; | ||||||
|   private $providerConfigPHIDs; |   private $providerConfigPHIDs; | ||||||
|  |   private $needAccountIdentifiers; | ||||||
|  |   private $rawAccountIdentifiers; | ||||||
|  |  | ||||||
|   public function withUserPHIDs(array $user_phids) { |   public function withUserPHIDs(array $user_phids) { | ||||||
|     $this->userPHIDs = $user_phids; |     $this->userPHIDs = $user_phids; | ||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function withAccountIDs(array $account_ids) { |  | ||||||
|     $this->accountIDs = $account_ids; |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function withAccountDomains(array $account_domains) { |  | ||||||
|     $this->accountDomains = $account_domains; |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function withAccountTypes(array $account_types) { |  | ||||||
|     $this->accountTypes = $account_types; |  | ||||||
|     return $this; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   public function withPHIDs(array $phids) { |   public function withPHIDs(array $phids) { | ||||||
|     $this->phids = $phids; |     $this->phids = $phids; | ||||||
|     return $this; |     return $this; | ||||||
| @@ -63,11 +47,21 @@ final class PhabricatorExternalAccountQuery | |||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function needAccountIdentifiers($need) { | ||||||
|  |     $this->needAccountIdentifiers = $need; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public function withProviderConfigPHIDs(array $phids) { |   public function withProviderConfigPHIDs(array $phids) { | ||||||
|     $this->providerConfigPHIDs = $phids; |     $this->providerConfigPHIDs = $phids; | ||||||
|     return $this; |     return $this; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public function withRawAccountIdentifiers(array $identifiers) { | ||||||
|  |     $this->rawAccountIdentifiers = $identifiers; | ||||||
|  |     return $this; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public function newResultObject() { |   public function newResultObject() { | ||||||
|     return new PhabricatorExternalAccount(); |     return new PhabricatorExternalAccount(); | ||||||
|   } |   } | ||||||
| @@ -132,6 +126,23 @@ final class PhabricatorExternalAccountQuery | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if ($this->needAccountIdentifiers) { | ||||||
|  |       $account_phids = mpull($accounts, 'getPHID'); | ||||||
|  |  | ||||||
|  |       $identifiers = id(new PhabricatorExternalAccountIdentifierQuery()) | ||||||
|  |         ->setViewer($viewer) | ||||||
|  |         ->setParentQuery($this) | ||||||
|  |         ->withExternalAccountPHIDs($account_phids) | ||||||
|  |         ->execute(); | ||||||
|  |  | ||||||
|  |       $identifiers = mgroup($identifiers, 'getExternalAccountPHID'); | ||||||
|  |       foreach ($accounts as $account) { | ||||||
|  |         $account_phid = $account->getPHID(); | ||||||
|  |         $account_identifiers = idx($identifiers, $account_phid, array()); | ||||||
|  |         $account->attachAccountIdentifiers($account_identifiers); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return $accounts; |     return $accounts; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -141,62 +152,98 @@ final class PhabricatorExternalAccountQuery | |||||||
|     if ($this->ids !== null) { |     if ($this->ids !== null) { | ||||||
|       $where[] = qsprintf( |       $where[] = qsprintf( | ||||||
|         $conn, |         $conn, | ||||||
|         'id IN (%Ld)', |         'account.id IN (%Ld)', | ||||||
|         $this->ids); |         $this->ids); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ($this->phids !== null) { |     if ($this->phids !== null) { | ||||||
|       $where[] = qsprintf( |       $where[] = qsprintf( | ||||||
|         $conn, |         $conn, | ||||||
|         'phid IN (%Ls)', |         'account.phid IN (%Ls)', | ||||||
|         $this->phids); |         $this->phids); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ($this->accountTypes !== null) { |  | ||||||
|       $where[] = qsprintf( |  | ||||||
|         $conn, |  | ||||||
|         'accountType IN (%Ls)', |  | ||||||
|         $this->accountTypes); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if ($this->accountDomains !== null) { |  | ||||||
|       $where[] = qsprintf( |  | ||||||
|         $conn, |  | ||||||
|         'accountDomain IN (%Ls)', |  | ||||||
|         $this->accountDomains); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if ($this->accountIDs !== null) { |  | ||||||
|       $where[] = qsprintf( |  | ||||||
|         $conn, |  | ||||||
|         'accountID IN (%Ls)', |  | ||||||
|         $this->accountIDs); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if ($this->userPHIDs !== null) { |     if ($this->userPHIDs !== null) { | ||||||
|       $where[] = qsprintf( |       $where[] = qsprintf( | ||||||
|         $conn, |         $conn, | ||||||
|         'userPHID IN (%Ls)', |         'account.userPHID IN (%Ls)', | ||||||
|         $this->userPHIDs); |         $this->userPHIDs); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ($this->accountSecrets !== null) { |     if ($this->accountSecrets !== null) { | ||||||
|       $where[] = qsprintf( |       $where[] = qsprintf( | ||||||
|         $conn, |         $conn, | ||||||
|         'accountSecret IN (%Ls)', |         'account.accountSecret IN (%Ls)', | ||||||
|         $this->accountSecrets); |         $this->accountSecrets); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ($this->providerConfigPHIDs !== null) { |     if ($this->providerConfigPHIDs !== null) { | ||||||
|       $where[] = qsprintf( |       $where[] = qsprintf( | ||||||
|         $conn, |         $conn, | ||||||
|         'providerConfigPHID IN (%Ls)', |         'account.providerConfigPHID IN (%Ls)', | ||||||
|         $this->providerConfigPHIDs); |         $this->providerConfigPHIDs); | ||||||
|  |  | ||||||
|  |       // If we have a list of ProviderConfig PHIDs and are joining the | ||||||
|  |       // identifiers table, also include the list as an additional constraint | ||||||
|  |       // on the identifiers table. | ||||||
|  |  | ||||||
|  |       // This does not change the query results (an Account and its | ||||||
|  |       // Identifiers always have the same ProviderConfig PHID) but it allows | ||||||
|  |       // us to use keys on the Identifier table more efficiently. | ||||||
|  |  | ||||||
|  |       if ($this->shouldJoinIdentifiersTable()) { | ||||||
|  |         $where[] = qsprintf( | ||||||
|  |           $conn, | ||||||
|  |           'identifier.providerConfigPHID IN (%Ls)', | ||||||
|  |           $this->providerConfigPHIDs); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if ($this->rawAccountIdentifiers !== null) { | ||||||
|  |       $hashes = array(); | ||||||
|  |  | ||||||
|  |       foreach ($this->rawAccountIdentifiers as $raw_identifier) { | ||||||
|  |         $hashes[] = PhabricatorHash::digestForIndex($raw_identifier); | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       $where[] = qsprintf( | ||||||
|  |         $conn, | ||||||
|  |         'identifier.identifierHash IN (%Ls)', | ||||||
|  |         $hashes); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return $where; |     return $where; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   protected function buildJoinClauseParts(AphrontDatabaseConnection $conn) { | ||||||
|  |     $joins = parent::buildJoinClauseParts($conn); | ||||||
|  |  | ||||||
|  |     if ($this->shouldJoinIdentifiersTable()) { | ||||||
|  |       $joins[] = qsprintf( | ||||||
|  |         $conn, | ||||||
|  |         'JOIN %R identifier ON account.phid = identifier.externalAccountPHID', | ||||||
|  |         new PhabricatorExternalAccountIdentifier()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $joins; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function shouldJoinIdentifiersTable() { | ||||||
|  |     return ($this->rawAccountIdentifiers !== null); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function shouldGroupQueryResultRows() { | ||||||
|  |     if ($this->shouldJoinIdentifiersTable()) { | ||||||
|  |       return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return parent::shouldGroupQueryResultRows(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function getPrimaryTableAlias() { | ||||||
|  |     return 'account'; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public function getQueryApplicationClass() { |   public function getQueryApplicationClass() { | ||||||
|     return 'PhabricatorPeopleApplication'; |     return 'PhabricatorPeopleApplication'; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -80,7 +80,7 @@ final class PhabricatorAuthSSHPrivateKey extends Phobject { | |||||||
|     if (!$err) { |     if (!$err) { | ||||||
|       if ($passphrase) { |       if ($passphrase) { | ||||||
|         execx( |         execx( | ||||||
|           'ssh-keygen -y -P %P -N %s -f %R', |           'ssh-keygen -p -P %P -N %s -f %R', | ||||||
|           $passphrase, |           $passphrase, | ||||||
|           '', |           '', | ||||||
|           $tmp); |           $tmp); | ||||||
|   | |||||||
| @@ -125,7 +125,13 @@ final class PhabricatorAuthPassword | |||||||
|     $hash = $hasher->getPasswordHashForStorage($digest); |     $hash = $hasher->getPasswordHashForStorage($digest); | ||||||
|     $raw_hash = $hash->openEnvelope(); |     $raw_hash = $hash->openEnvelope(); | ||||||
|  |  | ||||||
|     return $this->setPasswordHash($raw_hash); |     $result = $this->setPasswordHash($raw_hash); | ||||||
|  |     if ($result) { | ||||||
|  |       if ($object instanceof PhabricatorUser) { | ||||||
|  |         $object->updateHtaccessPassword($password); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return $result; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public function comparePassword( |   public function comparePassword( | ||||||
|   | |||||||
| @@ -4,7 +4,8 @@ final class PhabricatorAuthProviderConfig | |||||||
|   extends PhabricatorAuthDAO |   extends PhabricatorAuthDAO | ||||||
|   implements |   implements | ||||||
|     PhabricatorApplicationTransactionInterface, |     PhabricatorApplicationTransactionInterface, | ||||||
|     PhabricatorPolicyInterface { |     PhabricatorPolicyInterface, | ||||||
|  |     PhabricatorDestructibleInterface { | ||||||
|  |  | ||||||
|   protected $providerClass; |   protected $providerClass; | ||||||
|   protected $providerType; |   protected $providerType; | ||||||
| @@ -140,4 +141,33 @@ final class PhabricatorAuthProviderConfig | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /* -(  PhabricatorDestructibleInterface  )----------------------------------- */ | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   public function destroyObjectPermanently( | ||||||
|  |     PhabricatorDestructionEngine $engine) { | ||||||
|  |  | ||||||
|  |     $viewer = $engine->getViewer(); | ||||||
|  |     $config_phid = $this->getPHID(); | ||||||
|  |  | ||||||
|  |     $accounts = id(new PhabricatorExternalAccountQuery()) | ||||||
|  |       ->setViewer($viewer) | ||||||
|  |       ->withProviderConfigPHIDs(array($config_phid)) | ||||||
|  |       ->newIterator(); | ||||||
|  |     foreach ($accounts as $account) { | ||||||
|  |       $engine->destroyObject($account); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $identifiers = id(new PhabricatorExternalAccountIdentifierQuery()) | ||||||
|  |       ->setViewer($viewer) | ||||||
|  |       ->withProviderConfigPHIDs(array($config_phid)) | ||||||
|  |       ->newIterator(); | ||||||
|  |     foreach ($identifiers as $identifier) { | ||||||
|  |       $engine->destroyObject($identifier); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $this->delete(); | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,8 +37,6 @@ final class PhabricatorAuthAccountView extends AphrontView { | |||||||
|       $use_name = $username; |       $use_name = $username; | ||||||
|     } else if (strlen($realname)) { |     } else if (strlen($realname)) { | ||||||
|       $use_name = $realname; |       $use_name = $realname; | ||||||
|     } else { |  | ||||||
|       $use_name = $account->getAccountID(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $content[] = phutil_tag( |     $content[] = phutil_tag( | ||||||
| @@ -61,8 +59,6 @@ final class PhabricatorAuthAccountView extends AphrontView { | |||||||
|       ), |       ), | ||||||
|       array( |       array( | ||||||
|         $prov_name, |         $prov_name, | ||||||
|         " \xC2\xB7 ", |  | ||||||
|         $account->getAccountID(), |  | ||||||
|       )); |       )); | ||||||
|  |  | ||||||
|     $account_uri = $account->getAccountURI(); |     $account_uri = $account->getAccountURI(); | ||||||
|   | |||||||
| @@ -849,8 +849,8 @@ final class PhutilICSParser extends Phobject { | |||||||
|       ); |       ); | ||||||
|  |  | ||||||
|       // Load the map of Windows timezones. |       // Load the map of Windows timezones. | ||||||
|       $root_path = dirname(phutil_get_library_root('phutil')); |       $root_path = dirname(phutil_get_library_root('phabricator')); | ||||||
|       $windows_path = $root_path.'/resources/timezones/windows_timezones.json'; |       $windows_path = $root_path.'/resources/timezones/windows-timezones.json'; | ||||||
|       $windows_data = Filesystem::readFile($windows_path); |       $windows_data = Filesystem::readFile($windows_path); | ||||||
|       $windows_zones = phutil_json_decode($windows_data); |       $windows_zones = phutil_json_decode($windows_data); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -82,6 +82,7 @@ final class CelerityDefaultPostprocessor | |||||||
|       'alphablack'          => '0,0,0', |       'alphablack'          => '0,0,0', | ||||||
|  |  | ||||||
|       // Base Greys |       // Base Greys | ||||||
|  |       'thingreyborder'     => '#dadee8', | ||||||
|       'lightgreyborder'     => '#C7CCD9', |       'lightgreyborder'     => '#C7CCD9', | ||||||
|       'greyborder'          => '#A1A6B0', |       'greyborder'          => '#A1A6B0', | ||||||
|       'darkgreyborder'      => '#676A70', |       'darkgreyborder'      => '#676A70', | ||||||
| @@ -207,6 +208,9 @@ final class CelerityDefaultPostprocessor | |||||||
|       // Usually light yellow |       // Usually light yellow | ||||||
|       'gentle.highlight' => '#fdf3da', |       'gentle.highlight' => '#fdf3da', | ||||||
|       'gentle.highlight.border' => '#c9b8a8', |       'gentle.highlight.border' => '#c9b8a8', | ||||||
|  |       'gentle.highlight.background' => '#fffdf6', | ||||||
|  |  | ||||||
|  |       'highlight.bright' => '#fdf320', | ||||||
|  |  | ||||||
|       'paste.content' => '#fffef5', |       'paste.content' => '#fffef5', | ||||||
|       'paste.border' => '#e9dbcd', |       'paste.border' => '#e9dbcd', | ||||||
| @@ -240,6 +244,9 @@ final class CelerityDefaultPostprocessor | |||||||
|  |  | ||||||
|       'document.border' => '#dedee1', |       'document.border' => '#dedee1', | ||||||
|  |  | ||||||
|  |       'delete-color' => '#c0392b', | ||||||
|  |       'create-color' => '#139543', | ||||||
|  |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -17,6 +17,9 @@ final class CelerityRedGreenPostprocessor | |||||||
|       'new-bright' => 'rgba(152, 207, 235, .35)', |       'new-bright' => 'rgba(152, 207, 235, .35)', | ||||||
|       'old-background' => 'rgba(250, 212, 175, .3)', |       'old-background' => 'rgba(250, 212, 175, .3)', | ||||||
|       'old-bright' => 'rgba(250, 212, 175, .55)', |       'old-bright' => 'rgba(250, 212, 175, .55)', | ||||||
|  |  | ||||||
|  |       'delete-color' => '#e67e22', | ||||||
|  |       'create-color' => '#2980b9', | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -134,9 +134,17 @@ final class PhabricatorConduitAPIController | |||||||
|           $method_implementation); |           $method_implementation); | ||||||
|       case 'json': |       case 'json': | ||||||
|       default: |       default: | ||||||
|         return id(new AphrontJSONResponse()) |         $response = id(new AphrontJSONResponse()) | ||||||
|           ->setAddJSONShield(false) |           ->setAddJSONShield(false) | ||||||
|           ->setContent($response->toDictionary()); |           ->setContent($response->toDictionary()); | ||||||
|  |  | ||||||
|  |         $capabilities = $this->getConduitCapabilities(); | ||||||
|  |         if ($capabilities) { | ||||||
|  |           $capabilities = implode(' ', $capabilities); | ||||||
|  |           $response->addHeader('X-Conduit-Capabilities', $capabilities); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return $response; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -716,5 +724,14 @@ final class PhabricatorConduitAPIController | |||||||
|     return false; |     return false; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   private function getConduitCapabilities() { | ||||||
|  |     $capabilities = array(); | ||||||
|  |  | ||||||
|  |     if (AphrontRequestStream::supportsGzip()) { | ||||||
|  |       $capabilities[] = 'gzip'; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $capabilities; | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,6 +21,12 @@ final class PhabricatorConduitCallManagementWorkflow | |||||||
|               'File to read parameters from, or "-" to read from '. |               'File to read parameters from, or "-" to read from '. | ||||||
|               'stdin.'), |               'stdin.'), | ||||||
|           ), |           ), | ||||||
|  |           array( | ||||||
|  |             'name' => 'local', | ||||||
|  |             'help' => pht( | ||||||
|  |               'Force the request to execute in this process, rather than '. | ||||||
|  |               'proxying to another host in the cluster.'), | ||||||
|  |           ), | ||||||
|           array( |           array( | ||||||
|             'name' => 'as', |             'name' => 'as', | ||||||
|             'param' => 'username', |             'param' => 'username', | ||||||
| @@ -75,9 +81,17 @@ final class PhabricatorConduitCallManagementWorkflow | |||||||
|  |  | ||||||
|     $params = phutil_json_decode($input_json); |     $params = phutil_json_decode($input_json); | ||||||
|  |  | ||||||
|     $result = id(new ConduitCall($method, $params)) |     $call = id(new ConduitCall($method, $params)) | ||||||
|       ->setUser($actor) |       ->setUser($actor); | ||||||
|       ->execute(); |  | ||||||
|  |     $api_request = $call->getAPIRequest(); | ||||||
|  |  | ||||||
|  |     $is_local = $args->getArg('local'); | ||||||
|  |     if ($is_local) { | ||||||
|  |       $api_request->setIsClusterRequest(true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $result = $call->execute(); | ||||||
|  |  | ||||||
|     $output = array( |     $output = array( | ||||||
|       'result' => $result, |       'result' => $result, | ||||||
|   | |||||||
| @@ -129,8 +129,9 @@ abstract class ConduitParameterType extends Phobject { | |||||||
|       'true' => true, |       'true' => true, | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     if (!$strict && is_string($value) && isset($bool_strings[$value])) { |     $normal_value = phutil_utf8_strtolower($value); | ||||||
|       $value = $bool_strings[$value]; |     if (!$strict && is_string($value) && isset($bool_strings[$normal_value])) { | ||||||
|  |       $value = $bool_strings[$normal_value]; | ||||||
|     } else if (!is_bool($value)) { |     } else if (!is_bool($value)) { | ||||||
|       $this->raiseValidationException( |       $this->raiseValidationException( | ||||||
|         $request, |         $request, | ||||||
|   | |||||||
| @@ -37,13 +37,8 @@ final class PhabricatorConfigApplication extends PhabricatorApplication { | |||||||
|   public function getRoutes() { |   public function getRoutes() { | ||||||
|     return array( |     return array( | ||||||
|       '/config/' => array( |       '/config/' => array( | ||||||
|         '' => 'PhabricatorConfigListController', |         '' => 'PhabricatorConfigConsoleController', | ||||||
|         'application/' => 'PhabricatorConfigApplicationController', |  | ||||||
|         'all/' => 'PhabricatorConfigAllController', |  | ||||||
|         'history/' => 'PhabricatorConfigHistoryController', |  | ||||||
|         'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController', |         'edit/(?P<key>[\w\.\-]+)/' => 'PhabricatorConfigEditController', | ||||||
|         'group/(?P<key>[^/]+)/' => 'PhabricatorConfigGroupController', |  | ||||||
|         'version/' => 'PhabricatorConfigVersionController', |  | ||||||
|         'database/'. |         'database/'. | ||||||
|           '(?:(?P<ref>[^/]+)/'. |           '(?:(?P<ref>[^/]+)/'. | ||||||
|           '(?:(?P<database>[^/]+)/'. |           '(?:(?P<database>[^/]+)/'. | ||||||
| @@ -63,7 +58,7 @@ final class PhabricatorConfigApplication extends PhabricatorApplication { | |||||||
|           'purge/' => 'PhabricatorConfigPurgeCacheController', |           'purge/' => 'PhabricatorConfigPurgeCacheController', | ||||||
|         ), |         ), | ||||||
|         'module/' => array( |         'module/' => array( | ||||||
|           '(?P<module>[^/]+)/' => 'PhabricatorConfigModuleController', |           '(?:(?P<module>[^/]+)/)?' => 'PhabricatorConfigModuleController', | ||||||
|         ), |         ), | ||||||
|         'cluster/' => array( |         'cluster/' => array( | ||||||
|           'databases/' => 'PhabricatorConfigClusterDatabasesController', |           'databases/' => 'PhabricatorConfigClusterDatabasesController', | ||||||
| @@ -71,6 +66,12 @@ final class PhabricatorConfigApplication extends PhabricatorApplication { | |||||||
|           'repositories/' => 'PhabricatorConfigClusterRepositoriesController', |           'repositories/' => 'PhabricatorConfigClusterRepositoriesController', | ||||||
|           'search/' => 'PhabricatorConfigClusterSearchController', |           'search/' => 'PhabricatorConfigClusterSearchController', | ||||||
|         ), |         ), | ||||||
|  |         'settings/' => array( | ||||||
|  |           '' => 'PhabricatorConfigSettingsListController', | ||||||
|  |           '(?P<filter>advanced|all)/' | ||||||
|  |             => 'PhabricatorConfigSettingsListController', | ||||||
|  |           'history/' => 'PhabricatorConfigSettingsHistoryController', | ||||||
|  |         ), | ||||||
|       ), |       ), | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -53,20 +53,23 @@ final class PhabricatorAuthSetupCheck extends PhabricatorSetupCheck { | |||||||
|         "\n\n". |         "\n\n". | ||||||
|         'Leaving your authentication provider configuration unlocked '. |         'Leaving your authentication provider configuration unlocked '. | ||||||
|         'increases the damage that a compromised administrator account can '. |         'increases the damage that a compromised administrator account can '. | ||||||
|         'do to your install, by, for example, changing the authentication '. |         'do to your install. For example, an attacker who compromises an '. | ||||||
|         'provider to a server they control and intercepting usernames and '. |         'administrator account can change authentication providers to point '. | ||||||
|  |         'at a server they control and attempt to intercept usernames and '. | ||||||
|         'passwords.'. |         'passwords.'. | ||||||
|         "\n\n". |         "\n\n". | ||||||
|         'To prevent this attack, you should configure your authentication '. |         'To prevent this attack, you should configure authentication, and '. | ||||||
|         'providers, and then lock the configuration by doing `%s` '. |         'then lock the configuration by running "bin/auth lock" from the '. | ||||||
|         'from the command line. This will prevent changing the '. |         'command line. This will prevent changing the authentication config '. | ||||||
|         'authentication provider config without first doing `%s`.', |         'without first running "bin/auth unlock".'); | ||||||
|         'bin/auth lock', |  | ||||||
|         'bin/auth unlock'); |  | ||||||
|       $this |       $this | ||||||
|         ->newIssue('auth.config-unlocked') |         ->newIssue('auth.config-unlocked') | ||||||
|         ->setShortName(pht('Auth Config Unlocked')) |         ->setShortName(pht('Auth Config Unlocked')) | ||||||
|         ->setName(pht('Authenticaton Provider Configuration Unlocked')) |         ->setName(pht('Authenticaton Configuration Unlocked')) | ||||||
|  |         ->setSummary( | ||||||
|  |           pht( | ||||||
|  |             'Authentication configuration is currently unlocked. Once you '. | ||||||
|  |             'finish configuring authentication, you should lock it.')) | ||||||
|         ->setMessage($message) |         ->setMessage($message) | ||||||
|         ->addRelatedPhabricatorConfig('auth.lock-config') |         ->addRelatedPhabricatorConfig('auth.lock-config') | ||||||
|         ->addCommand( |         ->addCommand( | ||||||
|   | |||||||
| @@ -48,10 +48,17 @@ final class PhabricatorDaemonsSetupCheck extends PhabricatorSetupCheck { | |||||||
|  |  | ||||||
|     $expect_user = PhabricatorEnv::getEnvConfig('phd.user'); |     $expect_user = PhabricatorEnv::getEnvConfig('phd.user'); | ||||||
|     if (strlen($expect_user)) { |     if (strlen($expect_user)) { | ||||||
|  |  | ||||||
|  |       try { | ||||||
|         $all_daemons = id(new PhabricatorDaemonLogQuery()) |         $all_daemons = id(new PhabricatorDaemonLogQuery()) | ||||||
|           ->setViewer(PhabricatorUser::getOmnipotentUser()) |           ->setViewer(PhabricatorUser::getOmnipotentUser()) | ||||||
|           ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) |           ->withStatus(PhabricatorDaemonLogQuery::STATUS_ALIVE) | ||||||
|           ->execute(); |           ->execute(); | ||||||
|  |       } catch (Exception $ex) { | ||||||
|  |         // If this query fails for some reason, just skip this check. | ||||||
|  |         $all_daemons = array(); | ||||||
|  |       } | ||||||
|  |  | ||||||
|       foreach ($all_daemons as $daemon) { |       foreach ($all_daemons as $daemon) { | ||||||
|         $actual_user = $daemon->getRunningAsUser(); |         $actual_user = $daemon->getRunningAsUser(); | ||||||
|         if ($actual_user == $expect_user) { |         if ($actual_user == $expect_user) { | ||||||
|   | |||||||
| @@ -58,8 +58,7 @@ final class PhabricatorSecuritySetupCheck extends PhabricatorSetupCheck { | |||||||
|         ->setName(pht('Alternate File Domain Not Configured')) |         ->setName(pht('Alternate File Domain Not Configured')) | ||||||
|         ->setSummary( |         ->setSummary( | ||||||
|           pht( |           pht( | ||||||
|             'Increase security (and improve performance) by configuring '. |             'Improve security by configuring an alternate file domain.')) | ||||||
|             'a CDN or alternate file domain.')) |  | ||||||
|         ->setMessage( |         ->setMessage( | ||||||
|           pht( |           pht( | ||||||
|             'Phabricator is currently configured to serve user uploads '. |             'Phabricator is currently configured to serve user uploads '. | ||||||
|   | |||||||