mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	Compare commits
	
		
			949 Commits
		
	
	
		
			enterprise
			...
			1.3.5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a625ca49ec | ||
| 
						 | 
					96bd1c38dc | ||
| 
						 | 
					9748780192 | ||
| 
						 | 
					bc3f096918 | ||
| 
						 | 
					af4aac6836 | ||
| 
						 | 
					e5f7000a23 | ||
| 
						 | 
					00bf7b25b5 | ||
| 
						 | 
					2c6bfe136a | ||
| 
						 | 
					db51a1c547 | ||
| 
						 | 
					3f76745235 | ||
| 
						 | 
					b59b5cac35 | ||
| 
						 | 
					5dd330e769 | ||
| 
						 | 
					140e598a89 | ||
| 
						 | 
					8159c03205 | ||
| 
						 | 
					0d12dfd06f | ||
| 
						 | 
					6888826d5b | ||
| 
						 | 
					f0add4638c | ||
| 
						 | 
					974a9bd0f3 | ||
| 
						 | 
					aeb6a5df7c | ||
| 
						 | 
					94c35d8fb0 | ||
| 
						 | 
					1d40b2291c | ||
| 
						 | 
					d6a41b4fe3 | ||
| 
						 | 
					5bf6f05f60 | ||
| 
						 | 
					b69c6228af | ||
| 
						 | 
					f4be74dafc | ||
| 
						 | 
					abb1a13e31 | ||
| 
						 | 
					3c3238d8e1 | ||
| 
						 | 
					5accdf6d69 | ||
| 
						 | 
					1156a82297 | ||
| 
						 | 
					81fe34d011 | ||
| 
						 | 
					3caa743951 | ||
| 
						 | 
					45a8b050ac | ||
| 
						 | 
					b21a105a99 | ||
| 
						 | 
					8967029729 | ||
| 
						 | 
					9c0c5c57a7 | ||
| 
						 | 
					f31816072d | ||
| 
						 | 
					0ace7fe502 | ||
| 
						 | 
					3770142635 | ||
| 
						 | 
					441fa8ed9d | ||
| 
						 | 
					11a51cf943 | ||
| 
						 | 
					cc33b68d73 | ||
| 
						 | 
					fcf4731ed9 | ||
| 
						 | 
					8269b4dc76 | ||
| 
						 | 
					2348a83678 | ||
| 
						 | 
					ae4cb6df35 | ||
| 
						 | 
					a0006d5faf | ||
| 
						 | 
					6540807761 | ||
| 
						 | 
					2fb9560476 | ||
| 
						 | 
					d7618ff8dc | ||
| 
						 | 
					be844b628d | ||
| 
						 | 
					ce5e9093e6 | ||
| 
						 | 
					3e5e40a3ed | ||
| 
						 | 
					da5fe944e1 | ||
| 
						 | 
					ca4db5ac4b | ||
| 
						 | 
					95056c6681 | ||
| 
						 | 
					c0bf02b4c2 | ||
| 
						 | 
					49cf7abaed | ||
| 
						 | 
					827e7ad19c | ||
| 
						 | 
					a3c122eb41 | ||
| 
						 | 
					1be909a450 | ||
| 
						 | 
					3c1c14a7cc | ||
| 
						 | 
					ac8167062b | ||
| 
						 | 
					485c907721 | ||
| 
						 | 
					53f74ef06a | ||
| 
						 | 
					b6e2fd6e83 | ||
| 
						 | 
					cf17168c9f | ||
| 
						 | 
					78a9b301d0 | ||
| 
						 | 
					99fd2924cf | ||
| 
						 | 
					efa7a90ecc | ||
| 
						 | 
					38ca08b18f | ||
| 
						 | 
					4a858d7d1b | ||
| 
						 | 
					c5b44dc921 | ||
| 
						 | 
					32878e8343 | ||
| 
						 | 
					ade363f3af | ||
| 
						 | 
					b68d116e3a | ||
| 
						 | 
					858d0a984b | ||
| 
						 | 
					bfcae58cac | ||
| 
						 | 
					80a8725a03 | ||
| 
						 | 
					36a9dc2cf7 | ||
| 
						 | 
					5e0b6b809a | ||
| 
						 | 
					602077f75b | ||
| 
						 | 
					94d7ed006f | ||
| 
						 | 
					e29c473077 | ||
| 
						 | 
					23a81af8ad | ||
| 
						 | 
					7fc7e5ee8c | ||
| 
						 | 
					232de3015a | ||
| 
						 | 
					eff0d31dcd | ||
| 
						 | 
					176e3f4a54 | ||
| 
						 | 
					f340778798 | ||
| 
						 | 
					3ac95ddc1a | ||
| 
						 | 
					a59e41b5ee | ||
| 
						 | 
					9590d988c5 | ||
| 
						 | 
					21ac93ae9c | ||
| 
						 | 
					fcec80461b | ||
| 
						 | 
					25a9ccccf1 | ||
| 
						 | 
					b7bb55932a | ||
| 
						 | 
					3b84a9a010 | ||
| 
						 | 
					a5c1fc6d76 | ||
| 
						 | 
					b3dfacae19 | ||
| 
						 | 
					c0ec9e985a | ||
| 
						 | 
					eca3c3bfaa | ||
| 
						 | 
					87d2d543a5 | ||
| 
						 | 
					155958871d | ||
| 
						 | 
					166192fb57 | ||
| 
						 | 
					24dfa10556 | ||
| 
						 | 
					36445d1576 | ||
| 
						 | 
					7f8ef32704 | ||
| 
						 | 
					394a0aa774 | ||
| 
						 | 
					a8643e44b4 | ||
| 
						 | 
					9f0a6272fa | ||
| 
						 | 
					cf1aff661c | ||
| 
						 | 
					5be0c2902e | ||
| 
						 | 
					73264ab530 | ||
| 
						 | 
					0a3bdc20e9 | ||
| 
						 | 
					942e97d886 | ||
| 
						 | 
					d8b44606a3 | ||
| 
						 | 
					4e61c06903 | ||
| 
						 | 
					3239ca6728 | ||
| 
						 | 
					1f07cbed1e | ||
| 
						 | 
					36716fe518 | ||
| 
						 | 
					5768fd7f49 | ||
| 
						 | 
					bf8cc35edc | ||
| 
						 | 
					1f2aa2fcab | ||
| 
						 | 
					51841d5bcb | ||
| 
						 | 
					1d2efb46c1 | ||
| 
						 | 
					f1bf5ba24f | ||
| 
						 | 
					827a825c06 | ||
| 
						 | 
					17fd248f23 | ||
| 
						 | 
					930c64df8a | ||
| 
						 | 
					3e87c82d56 | ||
| 
						 | 
					50ccbc4230 | ||
| 
						 | 
					8549606eb3 | ||
| 
						 | 
					da84aa3412 | ||
| 
						 | 
					ab5e04ef36 | ||
| 
						 | 
					e130884c6a | ||
| 
						 | 
					c17e50e0c4 | ||
| 
						 | 
					a9cf471239 | ||
| 
						 | 
					33b7b2d021 | ||
| 
						 | 
					1a3bc517d9 | ||
| 
						 | 
					2e5c82203d | ||
| 
						 | 
					cecbab3609 | ||
| 
						 | 
					9eee250720 | ||
| 
						 | 
					a3d85f501b | ||
| 
						 | 
					3649c7be73 | ||
| 
						 | 
					f25f935c02 | ||
| 
						 | 
					3cfebbd9c0 | ||
| 
						 | 
					6f50a2703e | ||
| 
						 | 
					e78361f985 | ||
| 
						 | 
					83a653efce | ||
| 
						 | 
					a8261dd6ac | ||
| 
						 | 
					16e0f21687 | ||
| 
						 | 
					d0afb75619 | ||
| 
						 | 
					d281fc75fd | ||
| 
						 | 
					e3f38acbce | ||
| 
						 | 
					3f7cb34b00 | ||
| 
						 | 
					edf7e732a2 | ||
| 
						 | 
					f9f1fdc4d7 | ||
| 
						 | 
					f79adf830f | ||
| 
						 | 
					d702ddb3cf | ||
| 
						 | 
					63e576b811 | ||
| 
						 | 
					8778c4726a | ||
| 
						 | 
					24f6743288 | ||
| 
						 | 
					59b94a901c | ||
| 
						 | 
					80651c99cd | ||
| 
						 | 
					78277b5ee5 | ||
| 
						 | 
					3e61714035 | ||
| 
						 | 
					90bfc39d55 | ||
| 
						 | 
					ab9539cffe | ||
| 
						 | 
					e7dc77426a | ||
| 
						 | 
					ae0ae3dde8 | ||
| 
						 | 
					ecc07333af | ||
| 
						 | 
					15fe02b618 | ||
| 
						 | 
					d88efef74b | ||
| 
						 | 
					0aab583bb1 | ||
| 
						 | 
					9db521a931 | ||
| 
						 | 
					5ea3bf85de | ||
| 
						 | 
					e65d508907 | ||
| 
						 | 
					362f9c6c5f | ||
| 
						 | 
					dfdc34603e | ||
| 
						 | 
					9ded218950 | ||
| 
						 | 
					599742536b | ||
| 
						 | 
					64cccb2267 | ||
| 
						 | 
					15abf9ed31 | ||
| 
						 | 
					bd5fc484f0 | ||
| 
						 | 
					4b3874988f | ||
| 
						 | 
					ef320c6e95 | ||
| 
						 | 
					e41c00107d | ||
| 
						 | 
					32f6d1055d | ||
| 
						 | 
					d34d44e1d4 | ||
| 
						 | 
					ec5ed87ca0 | ||
| 
						 | 
					2cab113035 | ||
| 
						 | 
					d9f111ec28 | ||
| 
						 | 
					e95dfd78ed | ||
| 
						 | 
					58e5c654fa | ||
| 
						 | 
					13f3b448e5 | ||
| 
						 | 
					95afea9006 | ||
| 
						 | 
					bded0d9d54 | ||
| 
						 | 
					cb88147ca9 | ||
| 
						 | 
					1b5f9e4374 | ||
| 
						 | 
					5c6cd40fe7 | ||
| 
						 | 
					36c6f1e731 | ||
| 
						 | 
					3515a69e43 | ||
| 
						 | 
					d2979ab5d4 | ||
| 
						 | 
					222ea05a3a | ||
| 
						 | 
					1880e96a22 | ||
| 
						 | 
					b58867451d | ||
| 
						 | 
					4d0f7c7ea4 | ||
| 
						 | 
					9734d1ab3f | ||
| 
						 | 
					bfa70675cb | ||
| 
						 | 
					def426aa34 | ||
| 
						 | 
					6176dfd039 | ||
| 
						 | 
					9000d27f12 | ||
| 
						 | 
					e79447131f | ||
| 
						 | 
					0a6bb975c3 | ||
| 
						 | 
					53c2b3f6f4 | ||
| 
						 | 
					748f931999 | ||
| 
						 | 
					dd8eda4edc | ||
| 
						 | 
					bd66b2139b | ||
| 
						 | 
					664db6b622 | ||
| 
						 | 
					8cb7b759c6 | ||
| 
						 | 
					086d8eee22 | ||
| 
						 | 
					5b7f3466ba | ||
| 
						 | 
					809efc4f2b | ||
| 
						 | 
					e5cb2a468f | ||
| 
						 | 
					90e2f5053f | ||
| 
						 | 
					6a63303736 | ||
| 
						 | 
					f78abd2dcc | ||
| 
						 | 
					4a6e132a44 | ||
| 
						 | 
					1e3249c94e | ||
| 
						 | 
					a1237aa2b2 | ||
| 
						 | 
					bb45f8d8e3 | ||
| 
						 | 
					5a747ab690 | ||
| 
						 | 
					dfb1601aed | ||
| 
						 | 
					62973fce0f | ||
| 
						 | 
					3043859700 | ||
| 
						 | 
					7cd1d9665d | ||
| 
						 | 
					0a20f168a7 | ||
| 
						 | 
					86278804c9 | ||
| 
						 | 
					dc5a5ce1de | ||
| 
						 | 
					4bd93325de | ||
| 
						 | 
					a9023935e4 | ||
| 
						 | 
					dedc83e5dd | ||
| 
						 | 
					472898cfc6 | ||
| 
						 | 
					32783ebbfb | ||
| 
						 | 
					902edf5200 | ||
| 
						 | 
					580cdb55be | ||
| 
						 | 
					795f191fb3 | ||
| 
						 | 
					1e7d7c0b71 | ||
| 
						 | 
					7e78dc4ca1 | ||
| 
						 | 
					75d0146d33 | ||
| 
						 | 
					0d7f749ad8 | ||
| 
						 | 
					e2d416ad8b | ||
| 
						 | 
					04d3eb33b1 | ||
| 
						 | 
					6f77e68622 | ||
| 
						 | 
					be23e6d189 | ||
| 
						 | 
					6e55b4df8a | ||
| 
						 | 
					1629e77174 | ||
| 
						 | 
					127cdf63c6 | ||
| 
						 | 
					5f74e6e76d | ||
| 
						 | 
					54adbb1737 | ||
| 
						 | 
					7cffb41e13 | ||
| 
						 | 
					5b8894cd25 | ||
| 
						 | 
					05b0cbb36a | ||
| 
						 | 
					dcc3b3fe37 | ||
| 
						 | 
					2de3e2ebdd | ||
| 
						 | 
					8c88746912 | ||
| 
						 | 
					43c7ff64d1 | ||
| 
						 | 
					0dae10eab4 | ||
| 
						 | 
					e61de3e052 | ||
| 
						 | 
					2ffd022a5f | ||
| 
						 | 
					78f32dcbd8 | ||
| 
						 | 
					f792b67098 | ||
| 
						 | 
					46e224997e | ||
| 
						 | 
					ef50e74873 | ||
| 
						 | 
					7b9e027e77 | ||
| 
						 | 
					8461048a11 | ||
| 
						 | 
					c25d9679a5 | ||
| 
						 | 
					16e462d9d2 | ||
| 
						 | 
					ac63d942ce | ||
| 
						 | 
					29ed28af00 | ||
| 
						 | 
					81d0f7c172 | ||
| 
						 | 
					147304c676 | ||
| 
						 | 
					9c310c6cdd | ||
| 
						 | 
					c6ca60d6dc | ||
| 
						 | 
					01d3c0c6aa | ||
| 
						 | 
					f38aa4ca39 | ||
| 
						 | 
					dd71771a82 | ||
| 
						 | 
					e8ea761fbe | ||
| 
						 | 
					4702d8e9b3 | ||
| 
						 | 
					f5089e535d | ||
| 
						 | 
					2fb2300d1b | ||
| 
						 | 
					48f1a84d6e | ||
| 
						 | 
					494d02cc35 | ||
| 
						 | 
					81a2a20bbf | ||
| 
						 | 
					8ea139c772 | ||
| 
						 | 
					cf7ea9bef9 | ||
| 
						 | 
					e4fce10f46 | ||
| 
						 | 
					2f88b7dcd0 | ||
| 
						 | 
					c545a42a67 | ||
| 
						 | 
					466a678c2c | ||
| 
						 | 
					4d3f0cdc74 | ||
| 
						 | 
					802a3dd357 | ||
| 
						 | 
					d3822c5d7b | ||
| 
						 | 
					0b7ef24a34 | ||
| 
						 | 
					4eaf88e8d1 | ||
| 
						 | 
					0ae8e28635 | ||
| 
						 | 
					d865732e0d | ||
| 
						 | 
					1c22b48bb1 | ||
| 
						 | 
					910429f365 | ||
| 
						 | 
					64a0b86917 | ||
| 
						 | 
					2bb268476e | ||
| 
						 | 
					3ad140e5a7 | ||
| 
						 | 
					179bf06940 | ||
| 
						 | 
					15713964a5 | ||
| 
						 | 
					a0a537e0ce | ||
| 
						 | 
					2c1ef7d89e | ||
| 
						 | 
					f4239d60ca | ||
| 
						 | 
					53b02a694a | ||
| 
						 | 
					1eebcb472d | ||
| 
						 | 
					2c760ae735 | ||
| 
						 | 
					a901677be1 | ||
| 
						 | 
					6ba5271824 | ||
| 
						 | 
					517703ab47 | ||
| 
						 | 
					b9baf049e6 | ||
| 
						 | 
					8ecb555a98 | ||
| 
						 | 
					db0cec8d70 | ||
| 
						 | 
					83dafb662a | ||
| 
						 | 
					3c76c3fe54 | ||
| 
						 | 
					fc828ed116 | ||
| 
						 | 
					9738f2fa17 | ||
| 
						 | 
					a3de75bf8b | ||
| 
						 | 
					d3ebfbd042 | ||
| 
						 | 
					bb9ced6e57 | ||
| 
						 | 
					7b82db214c | ||
| 
						 | 
					01d018ba31 | ||
| 
						 | 
					35d22949ed | ||
| 
						 | 
					7e9c121ad3 | ||
| 
						 | 
					439b86fe3b | ||
| 
						 | 
					3f68c56554 | ||
| 
						 | 
					b3461ac3b5 | ||
| 
						 | 
					4f1388706c | ||
| 
						 | 
					1dbe00f164 | ||
| 
						 | 
					e241e6e833 | ||
| 
						 | 
					acccd2d5be | ||
| 
						 | 
					e8f63e2041 | ||
| 
						 | 
					8a8356221e | ||
| 
						 | 
					0f27554423 | ||
| 
						 | 
					a5063cf046 | ||
| 
						 | 
					693857a1f8 | ||
| 
						 | 
					eb1631f78d | ||
| 
						 | 
					7e786d5426 | ||
| 
						 | 
					d401d1cb47 | ||
| 
						 | 
					87d1809657 | ||
| 
						 | 
					f2e7f4cb67 | ||
| 
						 | 
					f63ee86730 | ||
| 
						 | 
					9c4764fe68 | ||
| 
						 | 
					187469ea86 | ||
| 
						 | 
					50c43b45ee | ||
| 
						 | 
					6b1adf11f7 | ||
| 
						 | 
					b2688bcf43 | ||
| 
						 | 
					fe0a1c2643 | ||
| 
						 | 
					0ca76e8cd8 | ||
| 
						 | 
					d515f92d20 | ||
| 
						 | 
					2a5826242d | ||
| 
						 | 
					718a6ea697 | ||
| 
						 | 
					a2c1fca488 | ||
| 
						 | 
					30e4729254 | ||
| 
						 | 
					23ef278d29 | ||
| 
						 | 
					0726ec5931 | ||
| 
						 | 
					0bc2f43e32 | ||
| 
						 | 
					2a5ec20295 | ||
| 
						 | 
					52944622f8 | ||
| 
						 | 
					7411ce9092 | ||
| 
						 | 
					569abda653 | ||
| 
						 | 
					12cb8ceae0 | ||
| 
						 | 
					752ff34f8f | ||
| 
						 | 
					748fb9afe5 | ||
| 
						 | 
					94ec1f3741 | ||
| 
						 | 
					6ff3070c8e | ||
| 
						 | 
					e4db196032 | ||
| 
						 | 
					6b13f4a3c9 | ||
| 
						 | 
					5147b52267 | ||
| 
						 | 
					a54d50ab2d | ||
| 
						 | 
					47873c181b | ||
| 
						 | 
					c90b76444d | ||
| 
						 | 
					307d367346 | ||
| 
						 | 
					710a802f49 | ||
| 
						 | 
					6c424e8446 | ||
| 
						 | 
					70ac98b860 | ||
| 
						 | 
					58429a617b | ||
| 
						 | 
					203c04fdb8 | ||
| 
						 | 
					0ea54a043e | ||
| 
						 | 
					6ac6fd5e56 | ||
| 
						 | 
					f62b9a199c | ||
| 
						 | 
					3cf0d40436 | ||
| 
						 | 
					27217fddb3 | ||
| 
						 | 
					5507575b7e | ||
| 
						 | 
					0b9884ce5b | ||
| 
						 | 
					23c108a05c | ||
| 
						 | 
					cb153967ec | ||
| 
						 | 
					8c72eddb72 | ||
| 
						 | 
					298e008cc2 | ||
| 
						 | 
					8e9c019b35 | ||
| 
						 | 
					4e1d86f775 | ||
| 
						 | 
					b5f7ed037c | ||
| 
						 | 
					b383884019 | ||
| 
						 | 
					e4dbe57c10 | ||
| 
						 | 
					ffc75cb074 | ||
| 
						 | 
					667a3a06cd | ||
| 
						 | 
					410e557bad | ||
| 
						 | 
					8b1199ee35 | ||
| 
						 | 
					148959f1b7 | ||
| 
						 | 
					8f8b2519ea | ||
| 
						 | 
					ef8b6e5a42 | ||
| 
						 | 
					8b74a3e052 | ||
| 
						 | 
					f7535a0a1b | ||
| 
						 | 
					d2d9d9cb01 | ||
| 
						 | 
					ddbb3a37fb | ||
| 
						 | 
					672603d6cd | ||
| 
						 | 
					1a47683d32 | ||
| 
						 | 
					0494e40c39 | ||
| 
						 | 
					5219851de4 | ||
| 
						 | 
					6d43b22ebe | ||
| 
						 | 
					1e7994d97d | ||
| 
						 | 
					a9e439d9e0 | ||
| 
						 | 
					0224fe2db6 | ||
| 
						 | 
					7053fd2a24 | ||
| 
						 | 
					7ed182c08f | ||
| 
						 | 
					768b3b5011 | ||
| 
						 | 
					b190a24f40 | ||
| 
						 | 
					08a6969f48 | ||
| 
						 | 
					50b763b12b | ||
| 
						 | 
					0b44b7eb4c | ||
| 
						 | 
					2fbb13be0a | ||
| 
						 | 
					52424cd67a | ||
| 
						 | 
					caef3f8bf3 | ||
| 
						 | 
					3498a04613 | ||
| 
						 | 
					5b080bd0cf | ||
| 
						 | 
					2f7af69091 | ||
| 
						 | 
					bd3f1c6a9e | ||
| 
						 | 
					bd20b295e1 | ||
| 
						 | 
					04f211bbff | ||
| 
						 | 
					2e1d5ffd1c | ||
| 
						 | 
					2cfeef606c | ||
| 
						 | 
					6759a78d07 | ||
| 
						 | 
					3fc779278b | ||
| 
						 | 
					9114715030 | ||
| 
						 | 
					8518801601 | ||
| 
						 | 
					80db1b9feb | ||
| 
						 | 
					56789e55b4 | ||
| 
						 | 
					55e762b069 | ||
| 
						 | 
					1e9efe441a | ||
| 
						 | 
					c147daa312 | ||
| 
						 | 
					94279c0522 | ||
| 
						 | 
					536449c6a4 | ||
| 
						 | 
					456e735725 | ||
| 
						 | 
					0a1d142d69 | ||
| 
						 | 
					3158075405 | ||
| 
						 | 
					7bc98d1634 | ||
| 
						 | 
					28245ce4e4 | ||
| 
						 | 
					c3ded56a7e | ||
| 
						 | 
					e60f76487f | ||
| 
						 | 
					1613cad6f6 | ||
| 
						 | 
					c39e657a3b | ||
| 
						 | 
					61c16a20b4 | ||
| 
						 | 
					35fe8bf81b | ||
| 
						 | 
					e6bb683922 | ||
| 
						 | 
					286bd3005d | ||
| 
						 | 
					c38c9cf894 | ||
| 
						 | 
					441688b41e | ||
| 
						 | 
					c69f1dae3f | ||
| 
						 | 
					e5467d3268 | ||
| 
						 | 
					a9235a74f4 | ||
| 
						 | 
					4f6ee6744d | ||
| 
						 | 
					16faed0a83 | ||
| 
						 | 
					fa440d0be2 | ||
| 
						 | 
					c5993c2d2d | ||
| 
						 | 
					405c3d7626 | ||
| 
						 | 
					f8b71fa497 | ||
| 
						 | 
					af3411cab8 | ||
| 
						 | 
					9162ef3e0f | ||
| 
						 | 
					bba2eb7622 | ||
| 
						 | 
					5bb4a74ec0 | ||
| 
						 | 
					6850835273 | ||
| 
						 | 
					9aa3de0664 | ||
| 
						 | 
					400e355a2f | ||
| 
						 | 
					84b59d4335 | ||
| 
						 | 
					be2a1c2893 | ||
| 
						 | 
					f760567b96 | ||
| 
						 | 
					7fce920522 | ||
| 
						 | 
					77e7947f61 | ||
| 
						 | 
					23e791a3b9 | ||
| 
						 | 
					a8d61fa930 | ||
| 
						 | 
					d52e5e551d | ||
| 
						 | 
					84fc8f16dd | ||
| 
						 | 
					b12b44579c | ||
| 
						 | 
					91e83731f0 | ||
| 
						 | 
					3889edd824 | ||
| 
						 | 
					0e129614cf | ||
| 
						 | 
					50bc5401a4 | ||
| 
						 | 
					a1538b4bab | ||
| 
						 | 
					c09b6914ba | ||
| 
						 | 
					86ff8cdd8c | ||
| 
						 | 
					9cefe46a1f | ||
| 
						 | 
					202ac0fe10 | ||
| 
						 | 
					4eded59dbe | ||
| 
						 | 
					c832543168 | ||
| 
						 | 
					ef81999f3f | ||
| 
						 | 
					163d93c15b | ||
| 
						 | 
					6d2c6f269d | ||
| 
						 | 
					8f7542f34d | ||
| 
						 | 
					8b1f0223fe | ||
| 
						 | 
					7f3ea34dc5 | ||
| 
						 | 
					26690adc47 | ||
| 
						 | 
					1c06e37245 | ||
| 
						 | 
					e7c8c322c0 | ||
| 
						 | 
					fa1333c026 | ||
| 
						 | 
					fa461e86fd | ||
| 
						 | 
					3dc9ee182f | ||
| 
						 | 
					6ec72a290d | ||
| 
						 | 
					cbb5878477 | ||
| 
						 | 
					065fcf1a1b | ||
| 
						 | 
					7cd814d92c | ||
| 
						 | 
					86d310a984 | ||
| 
						 | 
					f7b64827e4 | ||
| 
						 | 
					44bb9d58d1 | ||
| 
						 | 
					0d0c427f2b | ||
| 
						 | 
					080f7229fc | ||
| 
						 | 
					f1db96143a | ||
| 
						 | 
					72964a2194 | ||
| 
						 | 
					d2f773a99d | ||
| 
						 | 
					d445386adc | ||
| 
						 | 
					1653541e83 | ||
| 
						 | 
					fa37ac1d73 | ||
| 
						 | 
					9a5289b96c | ||
| 
						 | 
					b8de1dd13f | ||
| 
						 | 
					45002aa03f | ||
| 
						 | 
					d4fa917c49 | ||
| 
						 | 
					0376d26c79 | ||
| 
						 | 
					65e9d0bead | ||
| 
						 | 
					63097f32e5 | ||
| 
						 | 
					da66220524 | ||
| 
						 | 
					9648fd1f9a | ||
| 
						 | 
					7a509af38b | ||
| 
						 | 
					ff44fb6fcf | ||
| 
						 | 
					dfc34eb074 | ||
| 
						 | 
					d6617a991c | ||
| 
						 | 
					12309c61b6 | ||
| 
						 | 
					24c23c2290 | ||
| 
						 | 
					fcca1549b0 | ||
| 
						 | 
					8b3b33c182 | ||
| 
						 | 
					f4196ed6ef | ||
| 
						 | 
					9ea3198ddf | ||
| 
						 | 
					40164f4398 | ||
| 
						 | 
					fd7dd0bc2c | ||
| 
						 | 
					bd20a756f9 | ||
| 
						 | 
					4397c25976 | ||
| 
						 | 
					bdee9721ec | ||
| 
						 | 
					f45f0b1df6 | ||
| 
						 | 
					dfa45a3689 | ||
| 
						 | 
					d6f01ed7b9 | ||
| 
						 | 
					917a4363e7 | ||
| 
						 | 
					0fbfbf488b | ||
| 
						 | 
					e9acdd147f | ||
| 
						 | 
					2f01e9c51d | ||
| 
						 | 
					719d551de6 | ||
| 
						 | 
					d3f14ae860 | ||
| 
						 | 
					9d04b3d643 | ||
| 
						 | 
					5fd58cf249 | ||
| 
						 | 
					39f632134d | ||
| 
						 | 
					0ccb794007 | ||
| 
						 | 
					80ca037747 | ||
| 
						 | 
					c7586a7135 | ||
| 
						 | 
					6071a11419 | ||
| 
						 | 
					1c7918495c | ||
| 
						 | 
					72c9deb59e | ||
| 
						 | 
					43d866dd71 | ||
| 
						 | 
					c23028ec7a | ||
| 
						 | 
					ef23a4efe4 | ||
| 
						 | 
					2d3a7e5418 | ||
| 
						 | 
					105c742e92 | ||
| 
						 | 
					e993b8fc40 | ||
| 
						 | 
					3d7c3a6de3 | ||
| 
						 | 
					c3543b06f0 | ||
| 
						 | 
					bc9a9db9b3 | ||
| 
						 | 
					af16f6730e | ||
| 
						 | 
					0eda5cbfec | ||
| 
						 | 
					52478d684c | ||
| 
						 | 
					97511067df | ||
| 
						 | 
					e7ef654b45 | ||
| 
						 | 
					9d8758557b | ||
| 
						 | 
					65b6c80f07 | ||
| 
						 | 
					246a5737e7 | ||
| 
						 | 
					eda05d23bf | ||
| 
						 | 
					2090d6ee27 | ||
| 
						 | 
					27aaa3b1bf | ||
| 
						 | 
					cc9fe19a9f | ||
| 
						 | 
					3a8b663eb1 | ||
| 
						 | 
					b5ec6c9958 | ||
| 
						 | 
					c359499386 | ||
| 
						 | 
					b80af20541 | ||
| 
						 | 
					96f6939284 | ||
| 
						 | 
					d8108f944c | ||
| 
						 | 
					fb00ee79a0 | ||
| 
						 | 
					8f37c3f5fd | ||
| 
						 | 
					91fb286b0d | ||
| 
						 | 
					ae326c066f | ||
| 
						 | 
					a9f01e382a | ||
| 
						 | 
					66ecc7a6f2 | ||
| 
						 | 
					2429ed6eeb | ||
| 
						 | 
					095c82ecc4 | ||
| 
						 | 
					82dfc7b109 | ||
| 
						 | 
					23155bbbae | ||
| 
						 | 
					a983a62ad2 | ||
| 
						 | 
					6ef234ba80 | ||
| 
						 | 
					b343d322fe | ||
| 
						 | 
					05d911b913 | ||
| 
						 | 
					957486cc95 | ||
| 
						 | 
					e7769d9004 | ||
| 
						 | 
					aa9c98ef10 | ||
| 
						 | 
					30f89f4669 | ||
| 
						 | 
					fa37e91e5c | ||
| 
						 | 
					3f6e53db6e | ||
| 
						 | 
					86175e8627 | ||
| 
						 | 
					0165da405f | ||
| 
						 | 
					f66d864f45 | ||
| 
						 | 
					b5ca2631e6 | ||
| 
						 | 
					3772344e2d | ||
| 
						 | 
					280575aff0 | ||
| 
						 | 
					c0d104c110 | ||
| 
						 | 
					64ba85aa19 | ||
| 
						 | 
					b161f4cff9 | ||
| 
						 | 
					c17ed8dc8c | ||
| 
						 | 
					494868d21d | ||
| 
						 | 
					f82cbe855f | ||
| 
						 | 
					eebbf0d4ee | ||
| 
						 | 
					eb1032c9c2 | ||
| 
						 | 
					17b579911e | ||
| 
						 | 
					538d76e6ed | ||
| 
						 | 
					846dfd5105 | ||
| 
						 | 
					50db83508b | ||
| 
						 | 
					f3180b774b | ||
| 
						 | 
					de545d5fa0 | ||
| 
						 | 
					8efa04437d | ||
| 
						 | 
					54ae946061 | ||
| 
						 | 
					8efe4c0a1b | ||
| 
						 | 
					82a935080d | ||
| 
						 | 
					25a9eae74b | ||
| 
						 | 
					58c44fee3e | ||
| 
						 | 
					1b9752e10e | ||
| 
						 | 
					89f10d7e7a | ||
| 
						 | 
					e5e0ba9e7c | ||
| 
						 | 
					30f9fed766 | ||
| 
						 | 
					f495f79c90 | ||
| 
						 | 
					4721a9093c | ||
| 
						 | 
					9f4bc9fb72 | ||
| 
						 | 
					f999440cc6 | ||
| 
						 | 
					2a3a98228e | ||
| 
						 | 
					d069ad0bc7 | ||
| 
						 | 
					137f5e5980 | ||
| 
						 | 
					11fef6b627 | ||
| 
						 | 
					6b4fe69227 | ||
| 
						 | 
					9b41b30487 | ||
| 
						 | 
					868b071eb2 | ||
| 
						 | 
					5f7df38b8a | ||
| 
						 | 
					f445202ba5 | ||
| 
						 | 
					a4a47db9e0 | ||
| 
						 | 
					55fef4d60e | ||
| 
						 | 
					09dfc9a89b | ||
| 
						 | 
					eabd9341b6 | ||
| 
						 | 
					2da547efc6 | ||
| 
						 | 
					46d9f581ab | ||
| 
						 | 
					12c04151e9 | ||
| 
						 | 
					60d4c620b9 | ||
| 
						 | 
					eec12ff268 | ||
| 
						 | 
					16df239f39 | ||
| 
						 | 
					c753dfc9a8 | ||
| 
						 | 
					f2e8929b8a | ||
| 
						 | 
					ca031304b9 | ||
| 
						 | 
					1af7a9db1f | ||
| 
						 | 
					bdaf8b2cfe | ||
| 
						 | 
					6f67d94fc4 | ||
| 
						 | 
					28a6644384 | ||
| 
						 | 
					66734d46cf | ||
| 
						 | 
					4fbe78d037 | ||
| 
						 | 
					dfed7f0b7e | ||
| 
						 | 
					47f96dc2dd | ||
| 
						 | 
					38212f83fc | ||
| 
						 | 
					b21dc34eed | ||
| 
						 | 
					9634fccda7 | ||
| 
						 | 
					814aed7cbe | ||
| 
						 | 
					5c44fa9a29 | ||
| 
						 | 
					64b0550f58 | ||
| 
						 | 
					9c52818b93 | ||
| 
						 | 
					b23dc256e4 | ||
| 
						 | 
					204e7e7e90 | ||
| 
						 | 
					0e3af9b238 | ||
| 
						 | 
					3fbdfeee88 | ||
| 
						 | 
					406e3025fb | ||
| 
						 | 
					8155b8ea04 | ||
| 
						 | 
					2850800e48 | ||
| 
						 | 
					0dd209c813 | ||
| 
						 | 
					802bd6448c | ||
| 
						 | 
					577d8d33e1 | ||
| 
						 | 
					2ca49c3735 | ||
| 
						 | 
					40dd0c677e | ||
| 
						 | 
					bf17ea0ee4 | ||
| 
						 | 
					cd1e07fed3 | ||
| 
						 | 
					e8843be3d0 | ||
| 
						 | 
					8a16ea4cc6 | ||
| 
						 | 
					4d47f487cb | ||
| 
						 | 
					5ba0b6b633 | ||
| 
						 | 
					213c0b49bc | ||
| 
						 | 
					5696ff5ce6 | ||
| 
						 | 
					fbe67f5d84 | ||
| 
						 | 
					8bb359d194 | ||
| 
						 | 
					52d6973191 | ||
| 
						 | 
					f6cec22e6d | ||
| 
						 | 
					2aeb5dde67 | ||
| 
						 | 
					151370277c | ||
| 
						 | 
					adcec427b6 | ||
| 
						 | 
					f7518ea853 | ||
| 
						 | 
					2ac428ad7d | ||
| 
						 | 
					df7f85d3c3 | ||
| 
						 | 
					2761f1338d | ||
| 
						 | 
					fae92685ae | ||
| 
						 | 
					816c0a4393 | ||
| 
						 | 
					4e24b432c4 | ||
| 
						 | 
					66edc784f9 | ||
| 
						 | 
					87635b9e32 | ||
| 
						 | 
					c96ceeaea4 | ||
| 
						 | 
					88c8472a31 | ||
| 
						 | 
					8a8efdc537 | ||
| 
						 | 
					07bb7b2fee | ||
| 
						 | 
					e0bd15669a | ||
| 
						 | 
					7829e809c7 | ||
| 
						 | 
					d89696291f | ||
| 
						 | 
					dfc462c24d | ||
| 
						 | 
					b07f4efc13 | ||
| 
						 | 
					53021bf7d3 | ||
| 
						 | 
					600786983c | ||
| 
						 | 
					c673b3b0b1 | ||
| 
						 | 
					df39a7bde2 | ||
| 
						 | 
					d75412764e | ||
| 
						 | 
					2d0b9e2aa2 | ||
| 
						 | 
					db4770a577 | ||
| 
						 | 
					0f96f5064e | ||
| 
						 | 
					0b29a2f53a | ||
| 
						 | 
					230802ee22 | ||
| 
						 | 
					7a97d01719 | ||
| 
						 | 
					3450d05858 | ||
| 
						 | 
					de9d26126a | ||
| 
						 | 
					ba0d3605ae | ||
| 
						 | 
					0983809e6f | ||
| 
						 | 
					6b200b3088 | ||
| 
						 | 
					5807a44aee | ||
| 
						 | 
					dda8bf6d8a | ||
| 
						 | 
					a27610f560 | ||
| 
						 | 
					dc15546ba3 | ||
| 
						 | 
					99036efa06 | ||
| 
						 | 
					a2d2438f03 | ||
| 
						 | 
					8ea941e783 | ||
| 
						 | 
					1eae686443 | ||
| 
						 | 
					f4764e58c6 | ||
| 
						 | 
					5d0abd6f3f | ||
| 
						 | 
					98bc0b04c5 | ||
| 
						 | 
					a07299f1d6 | ||
| 
						 | 
					9da693c371 | ||
| 
						 | 
					1788f5c576 | ||
| 
						 | 
					6a803a88c8 | ||
| 
						 | 
					f30a62e33c | ||
| 
						 | 
					0ac73e4d73 | ||
| 
						 | 
					61611a2dac | ||
| 
						 | 
					4bc50c3560 | ||
| 
						 | 
					bf5ebf1d2d | ||
| 
						 | 
					f22665e710 | ||
| 
						 | 
					7e49396fc5 | ||
| 
						 | 
					c7a9e08105 | ||
| 
						 | 
					c9140a6def | ||
| 
						 | 
					5bb922200a | ||
| 
						 | 
					b822c83b02 | ||
| 
						 | 
					fab6b0f7ae | ||
| 
						 | 
					9d21787cd7 | ||
| 
						 | 
					f47a3c62e8 | ||
| 
						 | 
					630187d91b | ||
| 
						 | 
					243c327d0a | ||
| 
						 | 
					b80293c80d | ||
| 
						 | 
					e80c4f13b9 | ||
| 
						 | 
					3fb3b564ae | ||
| 
						 | 
					f605a7df22 | ||
| 
						 | 
					63bcf98e71 | ||
| 
						 | 
					9275901277 | ||
| 
						 | 
					840ba90512 | ||
| 
						 | 
					b51ea69db0 | ||
| 
						 | 
					7658886b02 | ||
| 
						 | 
					a547043831 | ||
| 
						 | 
					865c57fa72 | ||
| 
						 | 
					409bc7b657 | ||
| 
						 | 
					5aef8b8fad | ||
| 
						 | 
					4a58241b17 | ||
| 
						 | 
					240050093b | ||
| 
						 | 
					f93ccd4df1 | ||
| 
						 | 
					5dfd6eee2d | ||
| 
						 | 
					ccfaee8412 | ||
| 
						 | 
					efe8fe4650 | ||
| 
						 | 
					f304b93b91 | ||
| 
						 | 
					7ebb3ec05d | ||
| 
						 | 
					09958cbf66 | ||
| 
						 | 
					7fe74a9d2e | ||
| 
						 | 
					15f5884247 | ||
| 
						 | 
					dbb3bf6a4d | ||
| 
						 | 
					0e55e54bec | ||
| 
						 | 
					ffdfa203e8 | ||
| 
						 | 
					13045f953f | ||
| 
						 | 
					3cd33c0fea | ||
| 
						 | 
					7390b6ec53 | ||
| 
						 | 
					1d601134ed | ||
| 
						 | 
					5d013b78eb | ||
| 
						 | 
					cd16eb952c | ||
| 
						 | 
					54e8bb872c | ||
| 
						 | 
					8ec1d9b552 | ||
| 
						 | 
					71de0ac565 | ||
| 
						 | 
					7f2f1ad533 | ||
| 
						 | 
					f9d5a02710 | ||
| 
						 | 
					5ad256fee7 | ||
| 
						 | 
					fe826cdf2b | ||
| 
						 | 
					0dbcdb94af | ||
| 
						 | 
					d9bfef4848 | ||
| 
						 | 
					1686d27633 | ||
| 
						 | 
					f22885223f | ||
| 
						 | 
					305cf30c50 | ||
| 
						 | 
					b4e4a98de6 | ||
| 
						 | 
					7ebe3bf824 | ||
| 
						 | 
					568c33f294 | ||
| 
						 | 
					748e5b6da6 | ||
| 
						 | 
					f128ff6d53 | ||
| 
						 | 
					174a62eb7c | ||
| 
						 | 
					22e6ab4028 | ||
| 
						 | 
					94db0466a7 | ||
| 
						 | 
					ca92292550 | ||
| 
						 | 
					e16da5db45 | ||
| 
						 | 
					666252d749 | ||
| 
						 | 
					ef92c345ea | ||
| 
						 | 
					75c3e91a15 | ||
| 
						 | 
					8075c6e5a8 | ||
| 
						 | 
					2ca0015c0a | ||
| 
						 | 
					55a862cc23 | ||
| 
						 | 
					c729965b69 | ||
| 
						 | 
					b67d976809 | ||
| 
						 | 
					3a9bdec149 | ||
| 
						 | 
					47b877357d | ||
| 
						 | 
					1c4dcda639 | ||
| 
						 | 
					187796c3d4 | ||
| 
						 | 
					38a4011a52 | ||
| 
						 | 
					5631e7e624 | ||
| 
						 | 
					2a5dd139c8 | ||
| 
						 | 
					2dd3776bc1 | ||
| 
						 | 
					da874f8ec6 | ||
| 
						 | 
					07140e7f11 | ||
| 
						 | 
					2ce57fa5b9 | ||
| 
						 | 
					1a6929d9ae | ||
| 
						 | 
					8ce5404777 | ||
| 
						 | 
					8611cc3977 | ||
| 
						 | 
					e645574b14 | ||
| 
						 | 
					44564274a1 | ||
| 
						 | 
					f0c20d8acb | ||
| 
						 | 
					0244b50f0b | ||
| 
						 | 
					d177f49a96 | ||
| 
						 | 
					9d973ff106 | ||
| 
						 | 
					7822be5cd9 | ||
| 
						 | 
					d0572f50fb | ||
| 
						 | 
					b00ebd1bdf | ||
| 
						 | 
					cff698d210 | ||
| 
						 | 
					56f1c023ab | ||
| 
						 | 
					cdd43baf5d | ||
| 
						 | 
					b0d768b16b | ||
| 
						 | 
					01a04c3169 | ||
| 
						 | 
					8af170a3c3 | ||
| 
						 | 
					320c2b8eaf | ||
| 
						 | 
					de8509e40d | ||
| 
						 | 
					dc71961dd9 | ||
| 
						 | 
					de65bb8194 | ||
| 
						 | 
					4c4cd1ed8e | ||
| 
						 | 
					da3ac9ae1b | ||
| 
						 | 
					48476fcbc5 | ||
| 
						 | 
					2c56e692a2 | ||
| 
						 | 
					235baf5187 | ||
| 
						 | 
					9dd8779a3a | ||
| 
						 | 
					9d68048d1d | ||
| 
						 | 
					78a3da7fbe | ||
| 
						 | 
					25331d8bb2 | ||
| 
						 | 
					ee3cb60e3c | ||
| 
						 | 
					8f90baf1eb | ||
| 
						 | 
					34f9cf3aa6 | ||
| 
						 | 
					dbdc0a9721 | ||
| 
						 | 
					e7e2f3a79c | ||
| 
						 | 
					29250a6692 | ||
| 
						 | 
					8bae4d746d | ||
| 
						 | 
					4bc76b2d6d | ||
| 
						 | 
					6edb758136 | ||
| 
						 | 
					f1ee2c6503 | ||
| 
						 | 
					bbfd33185c | ||
| 
						 | 
					580b6949cc | ||
| 
						 | 
					64ff916ca2 | ||
| 
						 | 
					14281de262 | ||
| 
						 | 
					2c6d7e8e18 | ||
| 
						 | 
					2d09036466 | ||
| 
						 | 
					ebce82b136 | ||
| 
						 | 
					3d04f5f738 | ||
| 
						 | 
					8b58d8574b | ||
| 
						 | 
					6c4295ed5b | ||
| 
						 | 
					fa285fd1a9 | ||
| 
						 | 
					54e24a5765 | ||
| 
						 | 
					0b0b9b9379 | ||
| 
						 | 
					c33eeeee23 | ||
| 
						 | 
					89eef10d44 | ||
| 
						 | 
					4ebc4a4ef1 | ||
| 
						 | 
					d7e4429bb7 | ||
| 
						 | 
					36e2929ee2 | ||
| 
						 | 
					acec697fe7 | ||
| 
						 | 
					91445035bc | ||
| 
						 | 
					fb27cbcd01 | ||
| 
						 | 
					11ba6a17ab | ||
| 
						 | 
					aa90e265c2 | ||
| 
						 | 
					76ff3a526c | ||
| 
						 | 
					2fb7c0059d | ||
| 
						 | 
					41e3a89398 | ||
| 
						 | 
					98737a012e | ||
| 
						 | 
					044e3ced4f | ||
| 
						 | 
					e0efae4d59 | ||
| 
						 | 
					cf13874c9d | ||
| 
						 | 
					f4db89c7e9 | ||
| 
						 | 
					90bb689e13 | ||
| 
						 | 
					dd345bdece | ||
| 
						 | 
					3a6df13360 | ||
| 
						 | 
					25d461c8f5 | ||
| 
						 | 
					2efaf75b25 | ||
| 
						 | 
					19dcc3f385 | ||
| 
						 | 
					bd9cccffce | ||
| 
						 | 
					fcb8c106b1 | ||
| 
						 | 
					f4c514fbf3 | ||
| 
						 | 
					eaa777b612 | ||
| 
						 | 
					2530009123 | ||
| 
						 | 
					15da5628a9 | ||
| 
						 | 
					97d4f2b009 | ||
| 
						 | 
					f31b61ea5b | ||
| 
						 | 
					502852541b | ||
| 
						 | 
					addfcbfc30 | ||
| 
						 | 
					c63f881518 | 
							
								
								
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -7,12 +7,13 @@
 | 
				
			|||||||
/prod-static
 | 
					/prod-static
 | 
				
			||||||
/errors/*
 | 
					/errors/*
 | 
				
			||||||
*.sw[po]
 | 
					*.sw[po]
 | 
				
			||||||
.DS_Store
 | 
					*.DS_Store
 | 
				
			||||||
event_queues.pickle
 | 
					event_queues.pickle
 | 
				
			||||||
stats/
 | 
					stats/
 | 
				
			||||||
zerver/fixtures/available-migrations
 | 
					zerver/fixtures/available-migrations
 | 
				
			||||||
zerver/fixtures/migration-status
 | 
					zerver/fixtures/migration-status
 | 
				
			||||||
zerver/fixtures/test_data1.json
 | 
					zerver/fixtures/test_data1.json
 | 
				
			||||||
 | 
					zerver/tests/frontend/test_credentials.js
 | 
				
			||||||
.kdev4
 | 
					.kdev4
 | 
				
			||||||
zulip.kdev4
 | 
					zulip.kdev4
 | 
				
			||||||
memcached_prefix
 | 
					memcached_prefix
 | 
				
			||||||
@@ -26,3 +27,10 @@ manage.log
 | 
				
			|||||||
.kateproject.d/
 | 
					.kateproject.d/
 | 
				
			||||||
.kateproject
 | 
					.kateproject
 | 
				
			||||||
*.kate-swp
 | 
					*.kate-swp
 | 
				
			||||||
 | 
					event_queues.json
 | 
				
			||||||
 | 
					.vagrant
 | 
				
			||||||
 | 
					/zproject/dev-secrets.conf
 | 
				
			||||||
 | 
					static/third/gemoji/
 | 
				
			||||||
 | 
					static/third/zxcvbn/
 | 
				
			||||||
 | 
					tools/emoji_dump/bitmaps/
 | 
				
			||||||
 | 
					tools/emoji_dump/*.ttx
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										203
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										203
									
								
								LICENSE
									
									
									
									
									
								
							@@ -1,5 +1,202 @@
 | 
				
			|||||||
Copyright <20> 2012-2013 Zulip, Inc.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
This software is licensed under the Zulip Enterprise License Agreement.
 | 
					                                 Apache License
 | 
				
			||||||
 | 
					                           Version 2.0, January 2004
 | 
				
			||||||
 | 
					                        http://www.apache.org/licenses/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Zulip can be reached at support@zulip.com.
 | 
					   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   1. Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "License" shall mean the terms and conditions for use, reproduction,
 | 
				
			||||||
 | 
					      and distribution as defined by Sections 1 through 9 of this document.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Licensor" shall mean the copyright owner or entity authorized by
 | 
				
			||||||
 | 
					      the copyright owner that is granting the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Legal Entity" shall mean the union of the acting entity and all
 | 
				
			||||||
 | 
					      other entities that control, are controlled by, or are under common
 | 
				
			||||||
 | 
					      control with that entity. For the purposes of this definition,
 | 
				
			||||||
 | 
					      "control" means (i) the power, direct or indirect, to cause the
 | 
				
			||||||
 | 
					      direction or management of such entity, whether by contract or
 | 
				
			||||||
 | 
					      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
				
			||||||
 | 
					      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "You" (or "Your") shall mean an individual or Legal Entity
 | 
				
			||||||
 | 
					      exercising permissions granted by this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Source" form shall mean the preferred form for making modifications,
 | 
				
			||||||
 | 
					      including but not limited to software source code, documentation
 | 
				
			||||||
 | 
					      source, and configuration files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Object" form shall mean any form resulting from mechanical
 | 
				
			||||||
 | 
					      transformation or translation of a Source form, including but
 | 
				
			||||||
 | 
					      not limited to compiled object code, generated documentation,
 | 
				
			||||||
 | 
					      and conversions to other media types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Work" shall mean the work of authorship, whether in Source or
 | 
				
			||||||
 | 
					      Object form, made available under the License, as indicated by a
 | 
				
			||||||
 | 
					      copyright notice that is included in or attached to the work
 | 
				
			||||||
 | 
					      (an example is provided in the Appendix below).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Derivative Works" shall mean any work, whether in Source or Object
 | 
				
			||||||
 | 
					      form, that is based on (or derived from) the Work and for which the
 | 
				
			||||||
 | 
					      editorial revisions, annotations, elaborations, or other modifications
 | 
				
			||||||
 | 
					      represent, as a whole, an original work of authorship. For the purposes
 | 
				
			||||||
 | 
					      of this License, Derivative Works shall not include works that remain
 | 
				
			||||||
 | 
					      separable from, or merely link (or bind by name) to the interfaces of,
 | 
				
			||||||
 | 
					      the Work and Derivative Works thereof.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Contribution" shall mean any work of authorship, including
 | 
				
			||||||
 | 
					      the original version of the Work and any modifications or additions
 | 
				
			||||||
 | 
					      to that Work or Derivative Works thereof, that is intentionally
 | 
				
			||||||
 | 
					      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
				
			||||||
 | 
					      or by an individual or Legal Entity authorized to submit on behalf of
 | 
				
			||||||
 | 
					      the copyright owner. For the purposes of this definition, "submitted"
 | 
				
			||||||
 | 
					      means any form of electronic, verbal, or written communication sent
 | 
				
			||||||
 | 
					      to the Licensor or its representatives, including but not limited to
 | 
				
			||||||
 | 
					      communication on electronic mailing lists, source code control systems,
 | 
				
			||||||
 | 
					      and issue tracking systems that are managed by, or on behalf of, the
 | 
				
			||||||
 | 
					      Licensor for the purpose of discussing and improving the Work, but
 | 
				
			||||||
 | 
					      excluding communication that is conspicuously marked or otherwise
 | 
				
			||||||
 | 
					      designated in writing by the copyright owner as "Not a Contribution."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
				
			||||||
 | 
					      on behalf of whom a Contribution has been received by Licensor and
 | 
				
			||||||
 | 
					      subsequently incorporated within the Work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
				
			||||||
 | 
					      this License, each Contributor hereby grants to You a perpetual,
 | 
				
			||||||
 | 
					      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
				
			||||||
 | 
					      copyright license to reproduce, prepare Derivative Works of,
 | 
				
			||||||
 | 
					      publicly display, publicly perform, sublicense, and distribute the
 | 
				
			||||||
 | 
					      Work and such Derivative Works in Source or Object form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   3. Grant of Patent License. Subject to the terms and conditions of
 | 
				
			||||||
 | 
					      this License, each Contributor hereby grants to You a perpetual,
 | 
				
			||||||
 | 
					      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
				
			||||||
 | 
					      (except as stated in this section) patent license to make, have made,
 | 
				
			||||||
 | 
					      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
				
			||||||
 | 
					      where such license applies only to those patent claims licensable
 | 
				
			||||||
 | 
					      by such Contributor that are necessarily infringed by their
 | 
				
			||||||
 | 
					      Contribution(s) alone or by combination of their Contribution(s)
 | 
				
			||||||
 | 
					      with the Work to which such Contribution(s) was submitted. If You
 | 
				
			||||||
 | 
					      institute patent litigation against any entity (including a
 | 
				
			||||||
 | 
					      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
				
			||||||
 | 
					      or a Contribution incorporated within the Work constitutes direct
 | 
				
			||||||
 | 
					      or contributory patent infringement, then any patent licenses
 | 
				
			||||||
 | 
					      granted to You under this License for that Work shall terminate
 | 
				
			||||||
 | 
					      as of the date such litigation is filed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   4. Redistribution. You may reproduce and distribute copies of the
 | 
				
			||||||
 | 
					      Work or Derivative Works thereof in any medium, with or without
 | 
				
			||||||
 | 
					      modifications, and in Source or Object form, provided that You
 | 
				
			||||||
 | 
					      meet the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (a) You must give any other recipients of the Work or
 | 
				
			||||||
 | 
					          Derivative Works a copy of this License; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (b) You must cause any modified files to carry prominent notices
 | 
				
			||||||
 | 
					          stating that You changed the files; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (c) You must retain, in the Source form of any Derivative Works
 | 
				
			||||||
 | 
					          that You distribute, all copyright, patent, trademark, and
 | 
				
			||||||
 | 
					          attribution notices from the Source form of the Work,
 | 
				
			||||||
 | 
					          excluding those notices that do not pertain to any part of
 | 
				
			||||||
 | 
					          the Derivative Works; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (d) If the Work includes a "NOTICE" text file as part of its
 | 
				
			||||||
 | 
					          distribution, then any Derivative Works that You distribute must
 | 
				
			||||||
 | 
					          include a readable copy of the attribution notices contained
 | 
				
			||||||
 | 
					          within such NOTICE file, excluding those notices that do not
 | 
				
			||||||
 | 
					          pertain to any part of the Derivative Works, in at least one
 | 
				
			||||||
 | 
					          of the following places: within a NOTICE text file distributed
 | 
				
			||||||
 | 
					          as part of the Derivative Works; within the Source form or
 | 
				
			||||||
 | 
					          documentation, if provided along with the Derivative Works; or,
 | 
				
			||||||
 | 
					          within a display generated by the Derivative Works, if and
 | 
				
			||||||
 | 
					          wherever such third-party notices normally appear. The contents
 | 
				
			||||||
 | 
					          of the NOTICE file are for informational purposes only and
 | 
				
			||||||
 | 
					          do not modify the License. You may add Your own attribution
 | 
				
			||||||
 | 
					          notices within Derivative Works that You distribute, alongside
 | 
				
			||||||
 | 
					          or as an addendum to the NOTICE text from the Work, provided
 | 
				
			||||||
 | 
					          that such additional attribution notices cannot be construed
 | 
				
			||||||
 | 
					          as modifying the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      You may add Your own copyright statement to Your modifications and
 | 
				
			||||||
 | 
					      may provide additional or different license terms and conditions
 | 
				
			||||||
 | 
					      for use, reproduction, or distribution of Your modifications, or
 | 
				
			||||||
 | 
					      for any such Derivative Works as a whole, provided Your use,
 | 
				
			||||||
 | 
					      reproduction, and distribution of the Work otherwise complies with
 | 
				
			||||||
 | 
					      the conditions stated in this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
				
			||||||
 | 
					      any Contribution intentionally submitted for inclusion in the Work
 | 
				
			||||||
 | 
					      by You to the Licensor shall be under the terms and conditions of
 | 
				
			||||||
 | 
					      this License, without any additional terms or conditions.
 | 
				
			||||||
 | 
					      Notwithstanding the above, nothing herein shall supersede or modify
 | 
				
			||||||
 | 
					      the terms of any separate license agreement you may have executed
 | 
				
			||||||
 | 
					      with Licensor regarding such Contributions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   6. Trademarks. This License does not grant permission to use the trade
 | 
				
			||||||
 | 
					      names, trademarks, service marks, or product names of the Licensor,
 | 
				
			||||||
 | 
					      except as required for reasonable and customary use in describing the
 | 
				
			||||||
 | 
					      origin of the Work and reproducing the content of the NOTICE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
				
			||||||
 | 
					      agreed to in writing, Licensor provides the Work (and each
 | 
				
			||||||
 | 
					      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
				
			||||||
 | 
					      implied, including, without limitation, any warranties or conditions
 | 
				
			||||||
 | 
					      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
				
			||||||
 | 
					      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
				
			||||||
 | 
					      appropriateness of using or redistributing the Work and assume any
 | 
				
			||||||
 | 
					      risks associated with Your exercise of permissions under this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   8. Limitation of Liability. In no event and under no legal theory,
 | 
				
			||||||
 | 
					      whether in tort (including negligence), contract, or otherwise,
 | 
				
			||||||
 | 
					      unless required by applicable law (such as deliberate and grossly
 | 
				
			||||||
 | 
					      negligent acts) or agreed to in writing, shall any Contributor be
 | 
				
			||||||
 | 
					      liable to You for damages, including any direct, indirect, special,
 | 
				
			||||||
 | 
					      incidental, or consequential damages of any character arising as a
 | 
				
			||||||
 | 
					      result of this License or out of the use or inability to use the
 | 
				
			||||||
 | 
					      Work (including but not limited to damages for loss of goodwill,
 | 
				
			||||||
 | 
					      work stoppage, computer failure or malfunction, or any and all
 | 
				
			||||||
 | 
					      other commercial damages or losses), even if such Contributor
 | 
				
			||||||
 | 
					      has been advised of the possibility of such damages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   9. Accepting Warranty or Additional Liability. While redistributing
 | 
				
			||||||
 | 
					      the Work or Derivative Works thereof, You may choose to offer,
 | 
				
			||||||
 | 
					      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
				
			||||||
 | 
					      or other liability obligations and/or rights consistent with this
 | 
				
			||||||
 | 
					      License. However, in accepting such obligations, You may act only
 | 
				
			||||||
 | 
					      on Your own behalf and on Your sole responsibility, not on behalf
 | 
				
			||||||
 | 
					      of any other Contributor, and only if You agree to indemnify,
 | 
				
			||||||
 | 
					      defend, and hold each Contributor harmless for any liability
 | 
				
			||||||
 | 
					      incurred by, or claims asserted against, such Contributor by reason
 | 
				
			||||||
 | 
					      of your accepting any such warranty or additional liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   APPENDIX: How to apply the Apache License to your work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      To apply the Apache License to your work, attach the following
 | 
				
			||||||
 | 
					      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
				
			||||||
 | 
					      replaced with your own identifying information. (Don't include
 | 
				
			||||||
 | 
					      the brackets!)  The text should be enclosed in the appropriate
 | 
				
			||||||
 | 
					      comment syntax for the file format. We also recommend that a
 | 
				
			||||||
 | 
					      file or class name and description of purpose be included on the
 | 
				
			||||||
 | 
					      same "printed page" as the copyright notice for easier
 | 
				
			||||||
 | 
					      identification within third-party archives.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Copyright [yyyy] [name of copyright owner]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					   you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					   You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					   distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					   See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					   limitations under the License.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										201
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										201
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,201 @@
 | 
				
			|||||||
 | 
					Zulip
 | 
				
			||||||
 | 
					=====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zulip is a powerful, open source group chat application. Written in
 | 
				
			||||||
 | 
					Python and using the Django framework, Zulip supports both private
 | 
				
			||||||
 | 
					messaging and group chats via conversation streams.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zulip also supports fast search, drag-and-drop file uploads, image
 | 
				
			||||||
 | 
					previews, group private messages, audible notifications,
 | 
				
			||||||
 | 
					missed-message emails, desktop apps, and much more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Further information on the Zulip project and its features can be found
 | 
				
			||||||
 | 
					at https://www.zulip.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Contributing to Zulip
 | 
				
			||||||
 | 
					=====================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zulip welcomes all forms of contributions!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Before a pull request can be merged, you need to to sign the [Dropbox
 | 
				
			||||||
 | 
					Contributor License Agreement](https://opensource.dropbox.com/cla/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please run the tests (tools/test-all) before submitting your pull
 | 
				
			||||||
 | 
					request and read our [commit message style
 | 
				
			||||||
 | 
					guidelines](http://zulip.readthedocs.org/en/latest/code-style.html#commit-messages).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zulip has a growing collection of developer documentation including
 | 
				
			||||||
 | 
					detailed documentation on coding style available on [Read The
 | 
				
			||||||
 | 
					Docs](https://zulip.readthedocs.org/).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Zulip also has a [development discussion mailing list](https://groups.google.com/forum/#!forum/zulip-devel)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Feel free to send any questions or suggestions of areas where you'd
 | 
				
			||||||
 | 
					love to see more documentation to the list!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We recommend sending proposals for large features or refactorings to
 | 
				
			||||||
 | 
					the zulip-devel list for discussion and advice before getting too deep
 | 
				
			||||||
 | 
					into implementation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please report any security issues you discover to support@zulip.com.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Running Zulip in production
 | 
				
			||||||
 | 
					===========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is documented in https://zulip.org/server.html and README.prod.md.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Installing the Zulip Development environment
 | 
				
			||||||
 | 
					============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using Vagrant
 | 
				
			||||||
 | 
					-------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is the recommended approach, and is tested on OS X 10.10 as well as Ubuntu 14.04.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* If your host is OS X, download VirtualBox from
 | 
				
			||||||
 | 
					  <http://download.virtualbox.org/virtualbox/4.3.30/VirtualBox-4.3.30-101610-OSX.dmg>
 | 
				
			||||||
 | 
					  and install it.
 | 
				
			||||||
 | 
					* If your host is Ubuntu 14.04: 
 | 
				
			||||||
 | 
					  `sudo apt-get install vagrant lxc lxc-templates cgroup-lite redir && vagrant plugin install vagrant-lxc`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once that's done, simply change to your zulip directory and run
 | 
				
			||||||
 | 
					`vagrant up` in your terminal.  That will install the development
 | 
				
			||||||
 | 
					server inside a Vagrant guest.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once that finishes, you can run the development server as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					vagrant ssh -- -L9991:localhost:9991
 | 
				
			||||||
 | 
					# Now inside the container
 | 
				
			||||||
 | 
					cd /srv/zulip
 | 
				
			||||||
 | 
					source /srv/zulip-venv/bin/activate
 | 
				
			||||||
 | 
					./tools/run-dev.py --interface=''
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can now visit <http://localhost:9991/> in your browser.  To get
 | 
				
			||||||
 | 
					shell access to the virtual machine running the server, use `vagrant ssh`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(A small note on tools/run-dev.py: the `--interface=''` option will make
 | 
				
			||||||
 | 
					the development server listen on all network interfaces.  While this
 | 
				
			||||||
 | 
					is correct for the Vagrant guest sitting behind a NAT, you probably
 | 
				
			||||||
 | 
					don't want to use that option when using run-dev.py in other environments).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The run-dev.py console output will show any errors your Zulip
 | 
				
			||||||
 | 
					development server encounters.  It runs on top of Django's "manage.py
 | 
				
			||||||
 | 
					runserver" tool, which will automatically restart the Zulip server
 | 
				
			||||||
 | 
					whenever you save changes to Python code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					By hand
 | 
				
			||||||
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install the following non-Python dependencies:
 | 
				
			||||||
 | 
					 * libffi-dev — needed for some Python extensions
 | 
				
			||||||
 | 
					 * postgresql 9.1 or later — our database (also install development headers)
 | 
				
			||||||
 | 
					 * memcached (and headers)
 | 
				
			||||||
 | 
					 * rabbitmq-server
 | 
				
			||||||
 | 
					 * libldap2-dev
 | 
				
			||||||
 | 
					 * python-dev
 | 
				
			||||||
 | 
					 * redis-server — rate limiting
 | 
				
			||||||
 | 
					 * tsearch-extras — better text search
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					On Debian or Ubuntu systems:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					sudo apt-get install libffi-dev memcached rabbitmq-server libldap2-dev redis-server postgresql-server-dev-all libmemcached-dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If on 12.04 or wheezy:
 | 
				
			||||||
 | 
					sudo apt-get install postgresql-9.1
 | 
				
			||||||
 | 
					wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.1-tsearch-extras_0.1.2_amd64.deb
 | 
				
			||||||
 | 
					sudo dpkg -i postgresql-9.1-tsearch-extras_0.1.2_amd64.deb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If on 14.04:
 | 
				
			||||||
 | 
					sudo apt-get install postgresql-9.3
 | 
				
			||||||
 | 
					wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.3-tsearch-extras_0.1.2_amd64.deb
 | 
				
			||||||
 | 
					sudo dpkg -i postgresql-9.3-tsearch-extras_0.1.2_amd64.deb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If on 15.04 or jessie:
 | 
				
			||||||
 | 
					sudo apt-get install postgresql-9.4
 | 
				
			||||||
 | 
					wget https://dl.dropboxusercontent.com/u/283158365/zuliposs/postgresql-9.4-tsearch-extras_0.1_amd64.deb
 | 
				
			||||||
 | 
					sudo dpkg -i postgresql-9.4-tsearch-extras_0.1_amd64.deb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Then, all versions:
 | 
				
			||||||
 | 
					pip install -r requirements.txt
 | 
				
			||||||
 | 
					./scripts/setup/configure-rabbitmq
 | 
				
			||||||
 | 
					./tools/postgres-init-db
 | 
				
			||||||
 | 
					./tools/do-destroy-rebuild-database
 | 
				
			||||||
 | 
					./tools/emoji_dump/build_emoji
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To start the development server:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					./tools/run-dev.py
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					… and hit http://localhost:9991/.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Running the test suite
 | 
				
			||||||
 | 
					======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					One-time setup of test databases:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					./tools/postgres-init-test-db
 | 
				
			||||||
 | 
					./tools/do-destroy-rebuild-test-database
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Run all tests:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					./tools/test-all
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This runs the linter plus all of our test suites; they can all be run
 | 
				
			||||||
 | 
					separately (just read `tools/test-all` to see them).  You can also run
 | 
				
			||||||
 | 
					individual tests, e.g.:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					./tools/test-backend zerver.test_bugdown.BugdownTest.test_inline_youtube
 | 
				
			||||||
 | 
					./tools/test-js-with-casper 10-navigation.js
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Possible testing issues
 | 
				
			||||||
 | 
					=======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Casper tests are flaky on the Virtualbox environment (probably due
 | 
				
			||||||
 | 
					to some performance-sensitive races).  Until this issue is debugged,
 | 
				
			||||||
 | 
					you may need to rerun them to get them to pass.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When running the test suite, if you get an error like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					    sqlalchemy.exc.ProgrammingError: (ProgrammingError) function ts_match_locs_array(unknown, text, tsquery) does not exist
 | 
				
			||||||
 | 
					    LINE 2: ...ECT message_id, flags, subject, rendered_content, ts_match_l...
 | 
				
			||||||
 | 
					                                                                 ^
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					… then you need to install tsearch-extras, described above. Afterwards, re-run the `init*-db` and the `do-destroy-rebuild*-database` scripts.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					License
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright 2011-2015 Dropbox, Inc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The software includes some works released by third parties under other
 | 
				
			||||||
 | 
					free and open source licenses. Those works are redistributed under the
 | 
				
			||||||
 | 
					license terms under which the works were received. For more details,
 | 
				
			||||||
 | 
					see the ``THIRDPARTY`` file included with this distribution.
 | 
				
			||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
Requirements:
 | 
					This documents the process for installing Zulip in a production environment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Recommended requirements:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Server running Ubuntu Precise or Debian Wheezy
 | 
					* Server running Ubuntu Precise or Debian Wheezy
 | 
				
			||||||
* At least 2 CPUs for production use
 | 
					* At least 2 CPUs for production use
 | 
				
			||||||
@@ -8,22 +10,20 @@ Requirements:
 | 
				
			|||||||
  discuss with Zulip Support if this is an issue for you)
 | 
					  discuss with Zulip Support if this is an issue for you)
 | 
				
			||||||
* SSL Certificate for the host you're putting this on
 | 
					* SSL Certificate for the host you're putting this on
 | 
				
			||||||
  (e.g. https://zulip.example.com)
 | 
					  (e.g. https://zulip.example.com)
 | 
				
			||||||
* Zulip deployment key for the host that you're putting this on.
 | 
					 | 
				
			||||||
  You should have been provided with one by Zulip support.
 | 
					 | 
				
			||||||
* Email credentials for the service to send outgoing emails to users
 | 
					* Email credentials for the service to send outgoing emails to users
 | 
				
			||||||
  (e.g. missed message notifications, password reminders if you're not
 | 
					  (e.g. missed message notifications, password reminders if you're not
 | 
				
			||||||
  using SSO, etc.).
 | 
					  using SSO, etc.).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=======================================================================
 | 
					=======================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
How to install Zulip Enterprise:
 | 
					How to install Zulip in production:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These instructions should be followed as root.
 | 
					These instructions should be followed as root.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(1) Install the SSL certificates for your machine to
 | 
					(1) Install the SSL certificates for your machine to
 | 
				
			||||||
  /etc/ssl/private/zulip-enterprise.key
 | 
					  /etc/ssl/private/zulip.key
 | 
				
			||||||
  and
 | 
					  and
 | 
				
			||||||
  /etc/ssl/certs/zulip-enterprise.combined-chain.crt
 | 
					  /etc/ssl/certs/zulip.combined-chain.crt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(2) download zulip-server.tar.gz, and unpack to it /root/zulip, e.g.
 | 
					(2) download zulip-server.tar.gz, and unpack to it /root/zulip, e.g.
 | 
				
			||||||
tar -xf zulip-server-1.1.3.tar.gz
 | 
					tar -xf zulip-server-1.1.3.tar.gz
 | 
				
			||||||
@@ -45,14 +45,61 @@ successfully, the main installation process will be complete, and if
 | 
				
			|||||||
you are planning on using password authentication, you should be able
 | 
					you are planning on using password authentication, you should be able
 | 
				
			||||||
to visit the URL for your server and register for an account.
 | 
					to visit the URL for your server and register for an account.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(6) Subscribe to
 | 
				
			||||||
 | 
					https://groups.google.com/forum/#!forum/zulip-announce to get
 | 
				
			||||||
 | 
					announcements about new releases, security issues, etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					=======================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Maintaining Zulip in production:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* To upgrade to a new version, download the appropriate release
 | 
				
			||||||
 | 
					  tarball from https://www.zulip.org, and then run as root
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /home/zulip/deployments/current/scripts/upgrade-zulip <tarball>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  The upgrade process will shut down the service, run `apt-get
 | 
				
			||||||
 | 
					  upgrade` and any database migrations, and then bring the service
 | 
				
			||||||
 | 
					  back up.  This will result in some brief downtime for the service,
 | 
				
			||||||
 | 
					  which should be under 30 seconds unless there is an expensive
 | 
				
			||||||
 | 
					  transition involved.  Unless you have tested the upgrade in advance,
 | 
				
			||||||
 | 
					  we recommend doing upgrades at off hours.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You can create your own release tarballs from a copy of this
 | 
				
			||||||
 | 
					  repository using `tools/build-release-tarball`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* To update your settings, simply edit /etc/zulip/settings.py and then
 | 
				
			||||||
 | 
					  run /home/zulip/deployments/current/scripts/restart-server to
 | 
				
			||||||
 | 
					  restart the server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* You are responsible for running "apt-get upgrade" on your system on
 | 
				
			||||||
 | 
					  a regular basis to ensure that it is up to date with the latest
 | 
				
			||||||
 | 
					  security patches.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* To use the Zulip API with your Zulip server, you will need to use the
 | 
				
			||||||
 | 
					  API endpoint of e.g. "https://zulip.yourdomain.net/api".  Our Python
 | 
				
			||||||
 | 
					  API example scripts support this via the
 | 
				
			||||||
 | 
					  "--site=https://zulip.yourdomain.net" argument.  The API bindings
 | 
				
			||||||
 | 
					  support it via putting "site=https://zulip.yourdomain.net" in your
 | 
				
			||||||
 | 
					  .zuliprc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* Similarly, you will need to instruct your users to specify the URL
 | 
				
			||||||
 | 
					  for your Zulip server when using the Zulip desktop and mobile apps.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* As a measure to mitigate the impact of potential memory leaks in one
 | 
				
			||||||
 | 
					  of the Zulip daemons, the service automatically restarts itself
 | 
				
			||||||
 | 
					  every Sunday early morning.  See /etc/cron.d/restart-zulip for the
 | 
				
			||||||
 | 
					  precise configuration.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=======================================================================
 | 
					=======================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SSO Authentication:
 | 
					SSO Authentication:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
We integrate with your Single-Sign-On solution.  There are a few ways
 | 
					Zulip supports integrating with a corporate Single-Sign-On solution.
 | 
				
			||||||
to do it, but this section documents how to configure Zulip to use
 | 
					There are a few ways to do it, but this section documents how to
 | 
				
			||||||
your SSO solution that supports Apache and will set the REMOTE_USER
 | 
					configure Zulip to use an SSO solution that best supports Apache and
 | 
				
			||||||
variable:
 | 
					will set the REMOTE_USER variable:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(0) Check that /etc/zulip/settings.py has
 | 
					(0) Check that /etc/zulip/settings.py has
 | 
				
			||||||
"zproject.backends.ZulipRemoteUserBackend" as the only enabled value
 | 
					"zproject.backends.ZulipRemoteUserBackend" as the only enabled value
 | 
				
			||||||
@@ -88,43 +135,3 @@ To enable the Apache integration site.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Now you should be able to visit https://zulip.yourdomain.net/ and
 | 
					Now you should be able to visit https://zulip.yourdomain.net/ and
 | 
				
			||||||
login via the SSO solution.
 | 
					login via the SSO solution.
 | 
				
			||||||
 | 
					 | 
				
			||||||
=======================================================================
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Maintaining Zulip Enterprise:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* To upgrade to a new version, download the appropriate tarball from
 | 
					 | 
				
			||||||
  https://zulip.com/enterprise/download, and then run
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /home/zulip/deployments/current/scripts/upgrade-zulip <tarball>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  The upgrade process will result in some brief downtime for the
 | 
					 | 
				
			||||||
  service, which should be under 30 seconds unless there is an
 | 
					 | 
				
			||||||
  expensive transition involved, which would be mentioned in the
 | 
					 | 
				
			||||||
  release notes for the upgrade.  So we recommend doing upgrades at
 | 
					 | 
				
			||||||
  off hours.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* To update your settings, simply edit /etc/zulip/settings.py and then
 | 
					 | 
				
			||||||
  run /home/zulip/deployments/current/scripts/restart-server to
 | 
					 | 
				
			||||||
  restart the server
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* You are responsible for running "apt-get upgrade" on your system on
 | 
					 | 
				
			||||||
  a regular basis to ensure that it is up to date with the latest
 | 
					 | 
				
			||||||
  security patches.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* To use the Zulip API with Zulip Enterprise, you will need to use the
 | 
					 | 
				
			||||||
  API endpoint of e.g. "https://zulip.yourdomain.net/api".  Our Python
 | 
					 | 
				
			||||||
  API examples support this via the
 | 
					 | 
				
			||||||
  "--site=https://zulip.yourdomain.net" argument.  The API bindings
 | 
					 | 
				
			||||||
  support it via putting "site=https://zulip.yourdomain.net" in your
 | 
					 | 
				
			||||||
  .zuliprc.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* Contact support@zulip.com for our Nagios plugin for monitoring the
 | 
					 | 
				
			||||||
  service's health as you move it into production.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
* As a measure to mitigate the impact of potential memory leaks, the
 | 
					 | 
				
			||||||
  service automatically restarts itself once a week Sunday early
 | 
					 | 
				
			||||||
  morning.  See /etc/cron.d/restart-zulip for the precise
 | 
					 | 
				
			||||||
  configuration; if you'd like to change this setting, please be in
 | 
					 | 
				
			||||||
  touch with Zulip support on how to properly disable it (if you just
 | 
					 | 
				
			||||||
  delete the file, it will be re-added on the next Zulip upgrade).
 | 
					 | 
				
			||||||
							
								
								
									
										264
									
								
								THIRDPARTY
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								THIRDPARTY
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,264 @@
 | 
				
			|||||||
 | 
					Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 | 
				
			||||||
 | 
					Upstream-Name: Zulip
 | 
				
			||||||
 | 
					Upstream-Contact: Zulip Development Discussion <zulip-devel@googlegroups.com>
 | 
				
			||||||
 | 
					Source: https://zulip.org/
 | 
				
			||||||
 | 
					Comment: 
 | 
				
			||||||
 | 
					 Unless otherwise noted, the Zulip software is distributed under the Apache
 | 
				
			||||||
 | 
					 License, Version 2.0. The software includes some works released by third
 | 
				
			||||||
 | 
					 parties under other free and open source licenses. Those works are
 | 
				
			||||||
 | 
					 redistributed under the license terms under which the works were received.
 | 
				
			||||||
 | 
					 .
 | 
				
			||||||
 | 
					 While Dropbox has sought to provide complete and accurate licensing
 | 
				
			||||||
 | 
					 information for each FOSS package, Dropbox does not represent or warrant
 | 
				
			||||||
 | 
					 that the licensing information provided herein is correct or error-free.
 | 
				
			||||||
 | 
					 Recipients of the Zulip software should investigate the identified FOSS
 | 
				
			||||||
 | 
					 packages to confirm the accuracy of the licensing information provided.
 | 
				
			||||||
 | 
					 Recipients are also encouraged to notify Dropbox of any inaccurate
 | 
				
			||||||
 | 
					 information or errors found in these notices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: *
 | 
				
			||||||
 | 
					Copyright: 2011-2015 Dropbox, Inc.
 | 
				
			||||||
 | 
					License: Apache-2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: api/*
 | 
				
			||||||
 | 
					Copyright: 2012-2014 Dropbox, Inc
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: api/integrations/perforce/git_p4.py
 | 
				
			||||||
 | 
					Copyright: 2007 Simon Hausmann <simon@lst.de>,
 | 
				
			||||||
 | 
					 2007 Trolltech ASA
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					Comment: https://raw.github.com/git/git/34022ba/git-p4.py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: bots/jabber_mirror_backend.py
 | 
				
			||||||
 | 
					Copyright: 2013 Permabit, Inc., 2013-2014 Dropbox, Inc.
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: confirmation/*
 | 
				
			||||||
 | 
					Copyright: 2008, Jarek Zgoda <jarek.zgoda@gmail.com>
 | 
				
			||||||
 | 
					License: BSD-3-Clause
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: node_modules/handlebars/*
 | 
				
			||||||
 | 
					Copyright: 2011 Yehuda Katz
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/apt/*
 | 
				
			||||||
 | 
					Copyright: 2011, Evolving Web Inc.
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/common/*
 | 
				
			||||||
 | 
					Copyright: 2007, David Schmitt
 | 
				
			||||||
 | 
					License: BSD-3-Clause
 | 
				
			||||||
 | 
					Comment: https://github.com/DavidS/puppet-common
 | 
				
			||||||
 | 
					 Distribution includes a file `lib/puppet/parser/functions/ip_to_cron.rb` which
 | 
				
			||||||
 | 
					 we removed due to unclear license
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/stdlib/*
 | 
				
			||||||
 | 
					Copyright: 2011, Krzysztof Wilczynski
 | 
				
			||||||
 | 
					 2011, Puppet Labs Inc 
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					File: puppet/zulip_internal/files/mediawiki/Auth_remoteuser.php
 | 
				
			||||||
 | 
					Copyright: 2006 Otheus Shelling 
 | 
				
			||||||
 | 
					 2007 Rusty Burchfield
 | 
				
			||||||
 | 
					 2009 James Kinsman   
 | 
				
			||||||
 | 
					 2010 Daniel Thomas   
 | 
				
			||||||
 | 
					 2010 Ian Ward Comfort
 | 
				
			||||||
 | 
					License: GPL-2.0
 | 
				
			||||||
 | 
					Comment: Not linked.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/nagios_plugins/check_debian_packages
 | 
				
			||||||
 | 
					Copyright: 2005 Francesc Guasch
 | 
				
			||||||
 | 
					License: GPL-2.0
 | 
				
			||||||
 | 
					Comment: Not linked.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/nagios_plugins/check_postgres.pl
 | 
				
			||||||
 | 
					Copyright: 2007-2015 Greg Sabino Mullane
 | 
				
			||||||
 | 
					License: BSD-2-Clause
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/nagios_plugins/check_website_response.sh
 | 
				
			||||||
 | 
					Copyright: 2011 Chris Freeman
 | 
				
			||||||
 | 
					License: GPL-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/trac/cgi-bin/
 | 
				
			||||||
 | 
					Copyright: 2003-2009 Edgewall Software
 | 
				
			||||||
 | 
					 2003-2004 Jonas Borgström <jonas@edgewall.com>
 | 
				
			||||||
 | 
					License: BSD-3-Clause
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/pagerduty_nagios.pl
 | 
				
			||||||
 | 
					Copyright: 2011, PagerDuty, Inc.
 | 
				
			||||||
 | 
					License: BSD-3-Clause
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: puppet/zulip_internal/files/zulip-ec2-configure-interfaces
 | 
				
			||||||
 | 
					Copyright: 2013, Dropbox, Inc.
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/audio/zulip.*
 | 
				
			||||||
 | 
					Copyright: 2011 Vidsyn
 | 
				
			||||||
 | 
					License: CC-0-1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/styles/thirdparty-fonts.css
 | 
				
			||||||
 | 
					Copyright: 2012-2013 Dave Gandy
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/fontawesome/*
 | 
				
			||||||
 | 
					Copyright: 2012-2013 Dave Gandy
 | 
				
			||||||
 | 
					License: SIL-OFL-1.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/bootstrap/bootstrap-btn.css
 | 
				
			||||||
 | 
					Copyright: 2011-2014 Twitter, Inc
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/bootstrap/css/bootstrap-responsive.css static/third/bootstrap/css/bootstrap.css
 | 
				
			||||||
 | 
					Copyright: 2012 Twitter, Inc
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					Comment: The software has been modified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/bootstrap/js/bootstrap.js
 | 
				
			||||||
 | 
					Copyright: 2012 Twitter, Inc
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					Comment: The software has been modified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/bootstrap-notify/*
 | 
				
			||||||
 | 
					Copyright: 2013 Nijiko Yonskai
 | 
				
			||||||
 | 
					 2012 Goodybag, Inc.
 | 
				
			||||||
 | 
					 2012 Twitter, Inc
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					Comment: The software has been modified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/gemoji/images/emoji/unicode/* tools/emoji_dump/*.ttf
 | 
				
			||||||
 | 
					Copyright: Google, Inc.
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					Comment: These are actually Noto Emoji, not gemoji.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/handlebars/handlebars.runtime.js
 | 
				
			||||||
 | 
					Copyright: 2011 Yehuda Katz
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/html5-formdata/formdata.js
 | 
				
			||||||
 | 
					Copyright: 2010 François de Metz
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					Comment: See https://github.com/francois2metz/html5-formdata
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: src/zulip/static/third/jquery/*
 | 
				
			||||||
 | 
					Copyright: 2011, John Resig
 | 
				
			||||||
 | 
					 2011, The Dojo Foundation
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-autosize/jquery.autosize.js
 | 
				
			||||||
 | 
					Copyright: 2013 Jack Moore
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-caret/*
 | 
				
			||||||
 | 
					Copyright: 2010 C.F., Wong
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-filedrop/jquery.filedrop.js
 | 
				
			||||||
 | 
					Copyright: Resopollution
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-form/jquery.form.js
 | 
				
			||||||
 | 
					Copyright: M. Alsup
 | 
				
			||||||
 | 
					License: Expat or GPL-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-idle/jquery.idle.js
 | 
				
			||||||
 | 
					Copyright: 2011-2013 Henrique Boaventura
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					Comment: The software has been modified.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-mousewheel/jquery.mousewheel.js
 | 
				
			||||||
 | 
					Copyright: 2011 Brandon Aaron
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-perfect-scrollbar/*
 | 
				
			||||||
 | 
					Copyright: 2012 HyeonJe Jun
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-throttle-debounce/*
 | 
				
			||||||
 | 
					Copyright: 2010 "Cowboy" Ben Alman
 | 
				
			||||||
 | 
					License: Expat or GPL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/jquery-validate/*
 | 
				
			||||||
 | 
					Copyright: 2006 - 2011 Jörn Zaefferer
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: src/zulip/static/third/lazyload/*
 | 
				
			||||||
 | 
					Copyright: 2011 Ryan Grove
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/marked/*
 | 
				
			||||||
 | 
					Copyright: 2011-2013, Christopher Jeffrey
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/sockjs/sockjs-0.3.4.js
 | 
				
			||||||
 | 
					Copyright: 2011-2012 VMware, Inc.
 | 
				
			||||||
 | 
					 2012 Douglas Crockford
 | 
				
			||||||
 | 
					License: Expat and public-domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/sorttable/sorttable.js
 | 
				
			||||||
 | 
					Copyright: 2007 Stuart Langridge
 | 
				
			||||||
 | 
					License: X11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/sourcesans/*
 | 
				
			||||||
 | 
					Copyright: 2010, 2012, 2014 Adobe Systems Incorporated
 | 
				
			||||||
 | 
					License: SIL-OFL-1.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/spectrum/*
 | 
				
			||||||
 | 
					Copyright: 2013 Brian Grinstead
 | 
				
			||||||
 | 
					License: Expat 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/spin/spin.js
 | 
				
			||||||
 | 
					Copyright: 2011-2013 Felix Gnass
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/underscore/underscore.js
 | 
				
			||||||
 | 
					Copyright: 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					Comment: https://github.com/jashkenas/underscore/blob/master/LICENSE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/winchan/*
 | 
				
			||||||
 | 
					Copyright: 2012 Lloyd Hilaiel
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					Comment: https://github.com/mozilla/winchan
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/xdate/*
 | 
				
			||||||
 | 
					Copyright: 2010 C. F., Wong
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: static/third/zocial/*
 | 
				
			||||||
 | 
					Copyright: Sam Collins 
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: tools/inject-messages/othello
 | 
				
			||||||
 | 
					Copyright: Shakespeare
 | 
				
			||||||
 | 
					License: public-domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: tools/jslint/jslint.js
 | 
				
			||||||
 | 
					Copyright: 2002 Douglas Crockford
 | 
				
			||||||
 | 
					License: XXX-good-not-evil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: tools/python-proxy
 | 
				
			||||||
 | 
					Copyright: 2009 F.bio Domingues
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: tools/review
 | 
				
			||||||
 | 
					Copyright: 2010 Ksplice, Inc.
 | 
				
			||||||
 | 
					License: Apache-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: zerver/lib/bugdown/codehilite.py zerver/lib/bugdown/fenced_code.py
 | 
				
			||||||
 | 
					Copyright: 2006-2008 Waylan Limberg
 | 
				
			||||||
 | 
					License: BSD-3-Clause
 | 
				
			||||||
 | 
					Comment: https://pypi.python.org/pypi/Markdown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: zerver/lib/ccache.py
 | 
				
			||||||
 | 
					Copyright: 2013 David Benjamin and Alan Huang
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: zerver/tests/frontend/casperjs/*
 | 
				
			||||||
 | 
					Copyright: 2011-2012 Nicolas Perriault
 | 
				
			||||||
 | 
					 Joyent, Inc. and other Node contributors
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Files: zerver/tests/frontend/casperjs/modules/vendors/*
 | 
				
			||||||
 | 
					Copyright: 2011, Jeremy Ashkenas
 | 
				
			||||||
 | 
					License: Expat
 | 
				
			||||||
							
								
								
									
										34
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								Vagrantfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					# -*- mode: ruby -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VAGRANTFILE_API_VERSION = "2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # For LXC. VirtualBox hosts use a different box, described below.
 | 
				
			||||||
 | 
					  config.vm.box = "fgrehm/trusty64-lxc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # The Zulip development environment runs on 9991 on the guest.
 | 
				
			||||||
 | 
					  config.vm.network "forwarded_port", guest: 9991, host: 9991, host_ip: "127.0.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  config.vm.synced_folder ".", "/vagrant", disabled: true
 | 
				
			||||||
 | 
					  config.vm.synced_folder ".", "/srv/zulip"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  config.vm.provider "virtualbox" do |vb, override|
 | 
				
			||||||
 | 
					    override.vm.box = "ubuntu/trusty64"
 | 
				
			||||||
 | 
					    # 2GiB seemed reasonable here. The VM OOMs with only 1024MiB.
 | 
				
			||||||
 | 
					    vb.memory = 2048
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$provision_script = <<SCRIPT
 | 
				
			||||||
 | 
					set -x
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					sudo apt-get update
 | 
				
			||||||
 | 
					sudo apt-get install -y python-pbs
 | 
				
			||||||
 | 
					python /srv/zulip/provision.py
 | 
				
			||||||
 | 
					SCRIPT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  config.vm.provision "shell",
 | 
				
			||||||
 | 
					    # We want provision.py to be run with the permissions of the vagrant user.
 | 
				
			||||||
 | 
					    privileged: false,
 | 
				
			||||||
 | 
					    inline: $provision_script
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
@@ -17,6 +17,10 @@ python manage.py client_activity
 | 
				
			|||||||
python manage.py client_activity zulip.com
 | 
					python manage.py client_activity zulip.com
 | 
				
			||||||
python manage.py client_activity jesstess@zulip.com"""
 | 
					python manage.py client_activity jesstess@zulip.com"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_arguments(self, parser):
 | 
				
			||||||
 | 
					        parser.add_argument('arg', metavar='<arg>', type=str, nargs='?', default=None,
 | 
				
			||||||
 | 
					                            help="realm or user to estimate client activity for")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def compute_activity(self, user_activity_objects):
 | 
					    def compute_activity(self, user_activity_objects):
 | 
				
			||||||
        # Report data from the past week.
 | 
					        # Report data from the past week.
 | 
				
			||||||
        #
 | 
					        #
 | 
				
			||||||
@@ -49,21 +53,22 @@ python manage.py client_activity jesstess@zulip.com"""
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle(self, *args, **options):
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
        if len(args) == 0:
 | 
					        if options['arg'] is None:
 | 
				
			||||||
            # Report global activity.
 | 
					            # Report global activity.
 | 
				
			||||||
            self.compute_activity(UserActivity.objects.all())
 | 
					            self.compute_activity(UserActivity.objects.all())
 | 
				
			||||||
        elif len(args) == 1:
 | 
					        else:
 | 
				
			||||||
 | 
					            arg = options['arg']
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                # Report activity for a user.
 | 
					                # Report activity for a user.
 | 
				
			||||||
                user_profile = get_user_profile_by_email(args[0])
 | 
					                user_profile = get_user_profile_by_email(arg)
 | 
				
			||||||
                self.compute_activity(UserActivity.objects.filter(
 | 
					                self.compute_activity(UserActivity.objects.filter(
 | 
				
			||||||
                        user_profile=user_profile))
 | 
					                        user_profile=user_profile))
 | 
				
			||||||
            except UserProfile.DoesNotExist:
 | 
					            except UserProfile.DoesNotExist:
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    # Report activity for a realm.
 | 
					                    # Report activity for a realm.
 | 
				
			||||||
                    realm = get_realm(args[0])
 | 
					                    realm = get_realm(arg)
 | 
				
			||||||
                    self.compute_activity(UserActivity.objects.filter(
 | 
					                    self.compute_activity(UserActivity.objects.filter(
 | 
				
			||||||
                            user_profile__realm=realm))
 | 
					                            user_profile__realm=realm))
 | 
				
			||||||
                except Realm.DoesNotExist:
 | 
					                except Realm.DoesNotExist:
 | 
				
			||||||
                    print "Unknown user or domain %s" % (args[0],)
 | 
					                    print "Unknown user or domain %s" % (arg,)
 | 
				
			||||||
                    exit(1)
 | 
					                    exit(1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,10 @@ human_messages = Message.objects.filter(sending_client__name__in=HUMAN_CLIENT_LI
 | 
				
			|||||||
class Command(BaseCommand):
 | 
					class Command(BaseCommand):
 | 
				
			||||||
    help = "Generate statistics on realm activity."
 | 
					    help = "Generate statistics on realm activity."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_arguments(self, parser):
 | 
				
			||||||
 | 
					        parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
 | 
				
			||||||
 | 
					                            help="realm to generate statistics for")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def active_users(self, realm):
 | 
					    def active_users(self, realm):
 | 
				
			||||||
        # Has been active (on the website, for now) in the last 7 days.
 | 
					        # Has been active (on the website, for now) in the last 7 days.
 | 
				
			||||||
        activity_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=7)
 | 
					        activity_cutoff = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=7)
 | 
				
			||||||
@@ -64,9 +68,9 @@ class Command(BaseCommand):
 | 
				
			|||||||
        print "%.2f%% of" % (fraction * 100,), text
 | 
					        print "%.2f%% of" % (fraction * 100,), text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle(self, *args, **options):
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
        if args:
 | 
					        if options['realms']:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                realms = [Realm.objects.get(domain=domain) for domain in args]
 | 
					                realms = [Realm.objects.get(domain=domain) for domain in options['realms']]
 | 
				
			||||||
            except Realm.DoesNotExist, e:
 | 
					            except Realm.DoesNotExist, e:
 | 
				
			||||||
                print e
 | 
					                print e
 | 
				
			||||||
                exit(1)
 | 
					                exit(1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,14 @@ from zerver.models import Realm, Stream, Message, Subscription, Recipient
 | 
				
			|||||||
class Command(BaseCommand):
 | 
					class Command(BaseCommand):
 | 
				
			||||||
    help = "Generate statistics on the streams for a realm."
 | 
					    help = "Generate statistics on the streams for a realm."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_arguments(self, parser):
 | 
				
			||||||
 | 
					        parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
 | 
				
			||||||
 | 
					                            help="realm to generate statistics for")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle(self, *args, **options):
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
        if args:
 | 
					        if options['realms']:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                realms = [Realm.objects.get(domain=domain) for domain in args]
 | 
					                realms = [Realm.objects.get(domain=domain) for domain in options['realms']]
 | 
				
			||||||
            except Realm.DoesNotExist, e:
 | 
					            except Realm.DoesNotExist, e:
 | 
				
			||||||
                print e
 | 
					                print e
 | 
				
			||||||
                exit(1)
 | 
					                exit(1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,15 +9,19 @@ from zerver.models import UserProfile, Realm, Stream, Message
 | 
				
			|||||||
class Command(BaseCommand):
 | 
					class Command(BaseCommand):
 | 
				
			||||||
    help = "Generate statistics on user activity."
 | 
					    help = "Generate statistics on user activity."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def add_arguments(self, parser):
 | 
				
			||||||
 | 
					        parser.add_argument('realms', metavar='<realm>', type=str, nargs='*',
 | 
				
			||||||
 | 
					                            help="realm to generate statistics for")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def messages_sent_by(self, user, week):
 | 
					    def messages_sent_by(self, user, week):
 | 
				
			||||||
        start = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=(week + 1)*7)
 | 
					        start = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=(week + 1)*7)
 | 
				
			||||||
        end = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=week*7)
 | 
					        end = datetime.datetime.now(tz=pytz.utc) - datetime.timedelta(days=week*7)
 | 
				
			||||||
        return Message.objects.filter(sender=user, pub_date__gt=start, pub_date__lte=end).count()
 | 
					        return Message.objects.filter(sender=user, pub_date__gt=start, pub_date__lte=end).count()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def handle(self, *args, **options):
 | 
					    def handle(self, *args, **options):
 | 
				
			||||||
        if args:
 | 
					        if options['realms']:
 | 
				
			||||||
            try:
 | 
					            try:
 | 
				
			||||||
                realms = [Realm.objects.get(domain=domain) for domain in args]
 | 
					                realms = [Realm.objects.get(domain=domain) for domain in options['realms']]
 | 
				
			||||||
            except Realm.DoesNotExist, e:
 | 
					            except Realm.DoesNotExist, e:
 | 
				
			||||||
                print e
 | 
					                print e
 | 
				
			||||||
                exit(1)
 | 
					                exit(1)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -172,9 +172,7 @@ def realm_summary_table(realm_minutes):
 | 
				
			|||||||
                GROUP BY realm_id
 | 
					                GROUP BY realm_id
 | 
				
			||||||
            ) at_risk_counts
 | 
					            ) at_risk_counts
 | 
				
			||||||
            ON at_risk_counts.realm_id = realm.id
 | 
					            ON at_risk_counts.realm_id = realm.id
 | 
				
			||||||
        WHERE
 | 
					        WHERE EXISTS (
 | 
				
			||||||
            realm.domain not in ('customer4.invalid', 'wdaher.com')
 | 
					 | 
				
			||||||
        AND EXISTS (
 | 
					 | 
				
			||||||
                SELECT *
 | 
					                SELECT *
 | 
				
			||||||
                FROM zerver_useractivity ua
 | 
					                FROM zerver_useractivity ua
 | 
				
			||||||
                JOIN zerver_userprofile up
 | 
					                JOIN zerver_userprofile up
 | 
				
			||||||
@@ -226,11 +224,6 @@ def realm_summary_table(realm_minutes):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    # Count active sites
 | 
					    # Count active sites
 | 
				
			||||||
    def meets_goal(row):
 | 
					    def meets_goal(row):
 | 
				
			||||||
        # The wdaher.com realm doesn't count toward company goals for
 | 
					 | 
				
			||||||
        # obvious reasons, and customer4.invalid is essentially a dup
 | 
					 | 
				
			||||||
        # for users.customer4.invalid.
 | 
					 | 
				
			||||||
        if row['domain'] in ['customer4.invalid', 'wdaher.com']:
 | 
					 | 
				
			||||||
            return False
 | 
					 | 
				
			||||||
        return row['active_user_count'] >= 5
 | 
					        return row['active_user_count'] >= 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    num_active_sites = len(filter(meets_goal, rows))
 | 
					    num_active_sites = len(filter(meets_goal, rows))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,15 +30,12 @@ file is as follows:
 | 
				
			|||||||
    [api]
 | 
					    [api]
 | 
				
			||||||
    key=<api key from the web interface>
 | 
					    key=<api key from the web interface>
 | 
				
			||||||
    email=<your email address>
 | 
					    email=<your email address>
 | 
				
			||||||
 | 
					    site=<your Zulip server's URI>
 | 
				
			||||||
If you are using Zulip Enterprise, you should also add
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    site=<your Zulip Enterprise server's URI>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Alternatively, you may explicitly use "--user" and "--api-key" in our
 | 
					Alternatively, you may explicitly use "--user" and "--api-key" in our
 | 
				
			||||||
examples, which is especially useful if you are running several bots
 | 
					examples, which is especially useful if you are running several bots
 | 
				
			||||||
which share a home directory.  There is also a "--site" option for
 | 
					which share a home directory.  There is also a "--site" option for
 | 
				
			||||||
setting the Zulip Enterprise server on the command line.
 | 
					setting the Zulip server on the command line.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can obtain your Zulip API key, create bots, and manage bots all
 | 
					You can obtain your Zulip API key, create bots, and manage bots all
 | 
				
			||||||
from your Zulip [settings page](https://zulip.com/#settings).
 | 
					from your Zulip [settings page](https://zulip.com/#settings).
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ usage = """list-subscriptions --user=<bot's email address> --api-key=<bot's api
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Prints out a list of the user's subscriptions.
 | 
					Prints out a list of the user's subscriptions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example: list-subscriptions --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
					Example: list-subscriptions --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										51
									
								
								api/examples/print-events
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										51
									
								
								api/examples/print-events
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Copyright © 2012 Zulip, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					# of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					# in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					# copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					# furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					# all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
				
			||||||
 | 
					# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					# THE SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import optparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					usage = """print-events --user=<bot's email address> --api-key=<bot's api key> [options]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Prints out certain events received by the indicated bot or user matching the filter below.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example: print-events --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
 | 
				
			||||||
 | 
					import zulip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					parser = optparse.OptionParser(usage=usage)
 | 
				
			||||||
 | 
					parser.add_option_group(zulip.generate_option_group(parser))
 | 
				
			||||||
 | 
					(options, args) = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					client = zulip.init_from_options(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_event(event):
 | 
				
			||||||
 | 
					    print event
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This is a blocking call, and will continuously poll for new events
 | 
				
			||||||
 | 
					# Note also the filter here is messages to the stream Denmark; if you
 | 
				
			||||||
 | 
					# don't specify event_types it'll print all events.
 | 
				
			||||||
 | 
					client.call_on_each_event(print_event, event_types=["message"], narrow=[["stream", "Denmark"]])
 | 
				
			||||||
@@ -29,7 +29,7 @@ usage = """print-messages --user=<bot's email address> --api-key=<bot's api key>
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Prints out each message received by the indicated bot or user.
 | 
					Prints out each message received by the indicated bot or user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example: print-messages --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
					Example: print-messages --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,7 +29,7 @@ usage = """print-next-message --user=<bot's email address> --api-key=<bot's api
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Prints out the next message received by the user.
 | 
					Prints out the next message received by the user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example: print-next-messages --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
					Example: print-next-messages --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,8 +29,8 @@ usage = """subscribe --user=<bot's email address> --api-key=<bot's api key> [opt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Ensures the user is subscribed to the listed streams.
 | 
					Ensures the user is subscribed to the listed streams.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Examples: subscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
 | 
					Examples: subscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
 | 
				
			||||||
          subscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
 | 
					          subscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,8 +29,8 @@ usage = """unsubscribe  --user=<bot's email address> --api-key=<bot's api key> [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Ensures the user is not subscribed to the listed streams.
 | 
					Ensures the user is not subscribed to the listed streams.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Examples: unsubscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
 | 
					Examples: unsubscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams=foo
 | 
				
			||||||
          unsubscribe --user=tabbott@zulip.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
 | 
					          unsubscribe --user=username@example.com --api-key=a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5 --streams='foo bar'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
					You can omit --user and --api-key arguments if you have a properly set up ~/.zuliprc
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,7 +38,7 @@ ZULIP_STREAM_NAME = "asana"
 | 
				
			|||||||
### OPTIONAL CONFIGURATION ###
 | 
					### OPTIONAL CONFIGURATION ###
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set to None for logging to stdout when testing, and to a file for
 | 
					# Set to None for logging to stdout when testing, and to a file for
 | 
				
			||||||
# logging when deployed.
 | 
					# logging in production.
 | 
				
			||||||
#LOG_FILE = "/var/tmp/zulip_asana.log"
 | 
					#LOG_FILE = "/var/tmp/zulip_asana.log"
 | 
				
			||||||
LOG_FILE = None
 | 
					LOG_FILE = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -49,7 +49,7 @@ RESUME_FILE = "/var/tmp/zulip_asana.state"
 | 
				
			|||||||
# When initially started, how many hours of messages to include.
 | 
					# When initially started, how many hours of messages to include.
 | 
				
			||||||
ASANA_INITIAL_HISTORY_HOURS = 1
 | 
					ASANA_INITIAL_HISTORY_HOURS = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip API server URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If properly installed, the Zulip API should be in your import
 | 
					# If properly installed, the Zulip API should be in your import
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								api/integrations/asana/zulip_asana_mirror
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										19
									
								
								api/integrations/asana/zulip_asana_mirror
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -22,11 +22,17 @@
 | 
				
			|||||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
# THE SOFTWARE.
 | 
					# THE SOFTWARE.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The "zulip_asana_mirror" script is run continuously, possibly on a work computer
 | 
				
			||||||
 | 
					# or preferably on a server.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# When restarted, it will attempt to pick up where it left off.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# python-dateutil is a dependency for this script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import base64
 | 
					import base64
 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
import dateutil.parser
 | 
					
 | 
				
			||||||
import dateutil.tz
 | 
					 | 
				
			||||||
import json
 | 
					import json
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
@@ -34,6 +40,15 @@ import time
 | 
				
			|||||||
import urllib2
 | 
					import urllib2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    import dateutil.parser
 | 
				
			||||||
 | 
					    import dateutil.tz
 | 
				
			||||||
 | 
					except ImportError, e:
 | 
				
			||||||
 | 
					    print >>sys.stderr, e
 | 
				
			||||||
 | 
					    print >>sys.stderr, "Please install the python-dateutil package."
 | 
				
			||||||
 | 
					    exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sys.path.insert(0, os.path.dirname(__file__))
 | 
					sys.path.insert(0, os.path.dirname(__file__))
 | 
				
			||||||
import zulip_asana_config as config
 | 
					import zulip_asana_config as config
 | 
				
			||||||
VERSION = "0.9"
 | 
					VERSION = "0.9"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@ ZULIP_STREAM_NAME = "basecamp"
 | 
				
			|||||||
## path, but if not, set a custom path below
 | 
					## path, but if not, set a custom path below
 | 
				
			||||||
ZULIP_API_PATH = None
 | 
					ZULIP_API_PATH = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip API server URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you wish to log to a file rather than stdout/stderr,
 | 
					# If you wish to log to a file rather than stdout/stderr,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,7 +50,7 @@ ZULIP_TICKETS_STREAM_NAME = "tickets"
 | 
				
			|||||||
# path, but if not, set a custom path below
 | 
					# path, but if not, set a custom path below
 | 
				
			||||||
ZULIP_API_PATH = None
 | 
					ZULIP_API_PATH = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip API server URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you wish to log to a file rather than stdout/stderr,
 | 
					# If you wish to log to a file rather than stdout/stderr,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,12 +22,12 @@
 | 
				
			|||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
# THE SOFTWARE.
 | 
					# THE SOFTWARE.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The "codebase-mirror.py" script is run continuously, possibly on a work computer
 | 
					# The "zulip_codebase_mirror" script is run continuously, possibly on a work
 | 
				
			||||||
# or preferably on a server.
 | 
					# computer or preferably on a server.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# When restarted, it will attempt to pick up where it left off.
 | 
					# When restarted, it will attempt to pick up where it left off.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# You may need to install the python-requests library, as well as python-dateutil
 | 
					# python-dateutil is a dependency for this script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import requests
 | 
					import requests
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
@@ -37,7 +37,13 @@ import os
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
from datetime import datetime, timedelta
 | 
					from datetime import datetime, timedelta
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import dateutil.parser
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    import dateutil.parser
 | 
				
			||||||
 | 
					except ImportError, e:
 | 
				
			||||||
 | 
					    print >>sys.stderr, e
 | 
				
			||||||
 | 
					    print >>sys.stderr, "Please install the python-dateutil package."
 | 
				
			||||||
 | 
					    exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sys.path.insert(0, os.path.dirname(__file__))
 | 
					sys.path.insert(0, os.path.dirname(__file__))
 | 
				
			||||||
import zulip_codebase_config as config
 | 
					import zulip_codebase_config as config
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,5 +61,5 @@ def format_commit_message(author, subject, commit_id):
 | 
				
			|||||||
## path, but if not, set a custom path below
 | 
					## path, but if not, set a custom path below
 | 
				
			||||||
ZULIP_API_PATH = None
 | 
					ZULIP_API_PATH = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip server's API URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -136,7 +136,7 @@ def strip_tags(html):
 | 
				
			|||||||
def compute_entry_hash(entry):
 | 
					def compute_entry_hash(entry):
 | 
				
			||||||
    entry_time = entry.get("published", entry.get("updated"))
 | 
					    entry_time = entry.get("published", entry.get("updated"))
 | 
				
			||||||
    entry_id = entry.get("id", entry.get("link"))
 | 
					    entry_id = entry.get("id", entry.get("link"))
 | 
				
			||||||
    return hashlib.md5(entry_id + entry_time).hexdigest()
 | 
					    return hashlib.md5(entry_id + str(entry_time)).hexdigest()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def elide_subject(subject):
 | 
					def elide_subject(subject):
 | 
				
			||||||
    MAX_TOPIC_LENGTH = 60
 | 
					    MAX_TOPIC_LENGTH = 60
 | 
				
			||||||
@@ -184,7 +184,7 @@ for feed_url in feed_urls:
 | 
				
			|||||||
        entry_hash = compute_entry_hash(entry)
 | 
					        entry_hash = compute_entry_hash(entry)
 | 
				
			||||||
        # An entry has either been published or updated.
 | 
					        # An entry has either been published or updated.
 | 
				
			||||||
        entry_time  = entry.get("published_parsed", entry.get("updated_parsed"))
 | 
					        entry_time  = entry.get("published_parsed", entry.get("updated_parsed"))
 | 
				
			||||||
        if (time.time() - calendar.timegm(entry_time)) > OLDNESS_THRESHOLD * 60 * 60 * 24:
 | 
					        if entry_time is not None and (time.time() - calendar.timegm(entry_time)) > OLDNESS_THRESHOLD * 60 * 60 * 24:
 | 
				
			||||||
            # As a safeguard against misbehaving feeds, don't try to process
 | 
					            # As a safeguard against misbehaving feeds, don't try to process
 | 
				
			||||||
            # entries older than some threshold.
 | 
					            # entries older than some threshold.
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,5 +53,5 @@ def commit_notice_destination(path, commit):
 | 
				
			|||||||
## path, but if not, set a custom path below
 | 
					## path, but if not, set a custom path below
 | 
				
			||||||
ZULIP_API_PATH = None
 | 
					ZULIP_API_PATH = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip server's API URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,5 +47,5 @@ TRAC_NOTIFY_FIELDS = ["description", "summary", "resolution", "comment", "owner"
 | 
				
			|||||||
## path, but if not, set a custom path below
 | 
					## path, but if not, set a custom path below
 | 
				
			||||||
ZULIP_API_PATH = None
 | 
					ZULIP_API_PATH = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you're using Zulip Enterprise, set this to your Zulip Enterprise server
 | 
					# Set this to your Zulip API server URI
 | 
				
			||||||
ZULIP_SITE = "https://api.zulip.com"
 | 
					ZULIP_SITE = "https://api.zulip.com"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,9 +126,9 @@ except ConfigParser.NoOptionError:
 | 
				
			|||||||
    user_id = options.twitter_id
 | 
					    user_id = options.twitter_id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
client = zulip.Client(
 | 
					client = zulip.Client(
 | 
				
			||||||
    email=options.email,
 | 
					    email=options.zulip_email,
 | 
				
			||||||
    api_key=options.api_key,
 | 
					    api_key=options.zulip_api_key,
 | 
				
			||||||
    site=options.site,
 | 
					    site=options.zulip_site,
 | 
				
			||||||
    client="ZulipTwitter/" + VERSION,
 | 
					    client="ZulipTwitter/" + VERSION,
 | 
				
			||||||
    verbose=True)
 | 
					    verbose=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,8 @@ import sys
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import optparse
 | 
					import optparse
 | 
				
			||||||
import platform
 | 
					import platform
 | 
				
			||||||
 | 
					import urllib
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
from distutils.version import LooseVersion
 | 
					from distutils.version import LooseVersion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from ConfigParser import SafeConfigParser
 | 
					from ConfigParser import SafeConfigParser
 | 
				
			||||||
@@ -37,6 +39,8 @@ import logging
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
__version__ = "0.2.4"
 | 
					__version__ = "0.2.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					logger = logging.getLogger(__name__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Check that we have a recent enough version
 | 
					# Check that we have a recent enough version
 | 
				
			||||||
# Older versions don't provide the 'json' attribute on responses.
 | 
					# Older versions don't provide the 'json' attribute on responses.
 | 
				
			||||||
assert(LooseVersion(requests.__version__) >= LooseVersion('0.12.1'))
 | 
					assert(LooseVersion(requests.__version__) >= LooseVersion('0.12.1'))
 | 
				
			||||||
@@ -45,39 +49,91 @@ requests_json_is_function = callable(requests.Response.json)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
API_VERSTRING = "v1/"
 | 
					API_VERSTRING = "v1/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CountingBackoff(object):
 | 
				
			||||||
 | 
					    def __init__(self, maximum_retries=10, timeout_success_equivalent=None):
 | 
				
			||||||
 | 
					        self.number_of_retries = 0
 | 
				
			||||||
 | 
					        self.maximum_retries = maximum_retries
 | 
				
			||||||
 | 
					        self.timeout_success_equivalent = timeout_success_equivalent
 | 
				
			||||||
 | 
					        self.last_attempt_time = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def keep_going(self):
 | 
				
			||||||
 | 
					        self._check_success_timeout()
 | 
				
			||||||
 | 
					        return self.number_of_retries < self.maximum_retries
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def succeed(self):
 | 
				
			||||||
 | 
					        self.number_of_retries = 0
 | 
				
			||||||
 | 
					        self.last_attempt_time = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def fail(self):
 | 
				
			||||||
 | 
					        self._check_success_timeout()
 | 
				
			||||||
 | 
					        self.number_of_retries = min(self.number_of_retries + 1,
 | 
				
			||||||
 | 
					                                     self.maximum_retries)
 | 
				
			||||||
 | 
					        self.last_attempt_time = time.time()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _check_success_timeout(self):
 | 
				
			||||||
 | 
					        if (self.timeout_success_equivalent is not None
 | 
				
			||||||
 | 
					            and self.last_attempt_time != 0
 | 
				
			||||||
 | 
					            and time.time() - self.last_attempt_time > self.timeout_success_equivalent):
 | 
				
			||||||
 | 
					            self.number_of_retries = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RandomExponentialBackoff(CountingBackoff):
 | 
				
			||||||
 | 
					    def fail(self):
 | 
				
			||||||
 | 
					        super(RandomExponentialBackoff, self).fail()
 | 
				
			||||||
 | 
					        # Exponential growth with ratio sqrt(2); compute random delay
 | 
				
			||||||
 | 
					        # between x and 2x where x is growing exponentially
 | 
				
			||||||
 | 
					        delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
 | 
				
			||||||
 | 
					        delay = delay_scale + random.randint(1, delay_scale)
 | 
				
			||||||
 | 
					        message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            logger.warning(message)
 | 
				
			||||||
 | 
					        except NameError:
 | 
				
			||||||
 | 
					            print message
 | 
				
			||||||
 | 
					        time.sleep(delay)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def _default_client():
 | 
					def _default_client():
 | 
				
			||||||
    return "ZulipPython/" + __version__
 | 
					    return "ZulipPython/" + __version__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def generate_option_group(parser):
 | 
					def generate_option_group(parser, prefix=''):
 | 
				
			||||||
    group = optparse.OptionGroup(parser, 'API configuration')
 | 
					    group = optparse.OptionGroup(parser, 'Zulip API configuration')
 | 
				
			||||||
    group.add_option('--site',
 | 
					    group.add_option('--%ssite' % (prefix,),
 | 
				
			||||||
                     help="Zulip Enterprise server URI (if using Zulip Enterprise)",
 | 
					                     dest="zulip_site",
 | 
				
			||||||
 | 
					                     help="Zulip server URI",
 | 
				
			||||||
                     default=None)
 | 
					                     default=None)
 | 
				
			||||||
    group.add_option('--api-key',
 | 
					    group.add_option('--%sapi-key' % (prefix,),
 | 
				
			||||||
 | 
					                     dest="zulip_api_key",
 | 
				
			||||||
                     action='store')
 | 
					                     action='store')
 | 
				
			||||||
    group.add_option('--user',
 | 
					    group.add_option('--%suser' % (prefix,),
 | 
				
			||||||
                     dest='email',
 | 
					                     dest='zulip_email',
 | 
				
			||||||
                     help='Email address of the calling bot or user.')
 | 
					                     help='Email address of the calling bot or user.')
 | 
				
			||||||
    group.add_option('--config-file',
 | 
					    group.add_option('--%sconfig-file' % (prefix,),
 | 
				
			||||||
                     action='store',
 | 
					                     action='store',
 | 
				
			||||||
 | 
					                     dest="zulip_config_file",
 | 
				
			||||||
                     help='Location of an ini file containing the\nabove information. (default ~/.zuliprc)')
 | 
					                     help='Location of an ini file containing the\nabove information. (default ~/.zuliprc)')
 | 
				
			||||||
    group.add_option('-v', '--verbose',
 | 
					    group.add_option('-v', '--verbose',
 | 
				
			||||||
                     action='store_true',
 | 
					                     action='store_true',
 | 
				
			||||||
                     help='Provide detailed output.')
 | 
					                     help='Provide detailed output.')
 | 
				
			||||||
    group.add_option('--client',
 | 
					    group.add_option('--%sclient' % (prefix,),
 | 
				
			||||||
                     action='store',
 | 
					                     action='store',
 | 
				
			||||||
                     default=None,
 | 
					                     default=None,
 | 
				
			||||||
 | 
					                     dest="zulip_client",
 | 
				
			||||||
                     help=optparse.SUPPRESS_HELP)
 | 
					                     help=optparse.SUPPRESS_HELP)
 | 
				
			||||||
    return group
 | 
					    return group
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def init_from_options(options, client=None):
 | 
					def init_from_options(options, client=None):
 | 
				
			||||||
    if options.client is not None:
 | 
					    if options.zulip_client is not None:
 | 
				
			||||||
        client = options.client
 | 
					        client = options.zulip_client
 | 
				
			||||||
    elif client is None:
 | 
					    elif client is None:
 | 
				
			||||||
        client = _default_client()
 | 
					        client = _default_client()
 | 
				
			||||||
    return Client(email=options.email, api_key=options.api_key,
 | 
					    return Client(email=options.zulip_email, api_key=options.zulip_api_key,
 | 
				
			||||||
                  config_file=options.config_file, verbose=options.verbose,
 | 
					                  config_file=options.zulip_config_file, verbose=options.verbose,
 | 
				
			||||||
                  site=options.site, client=client)
 | 
					                  site=options.zulip_site, client=client)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_default_config_filename():
 | 
				
			||||||
 | 
					    config_file = os.path.join(os.environ["HOME"], ".zuliprc")
 | 
				
			||||||
 | 
					    if (not os.path.exists(config_file) and
 | 
				
			||||||
 | 
					        os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
 | 
				
			||||||
 | 
					        raise RuntimeError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n  mv ~/.humbugrc ~/.zuliprc\n")
 | 
				
			||||||
 | 
					    return config_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Client(object):
 | 
					class Client(object):
 | 
				
			||||||
    def __init__(self, email=None, api_key=None, config_file=None,
 | 
					    def __init__(self, email=None, api_key=None, config_file=None,
 | 
				
			||||||
@@ -87,10 +143,7 @@ class Client(object):
 | 
				
			|||||||
            client = _default_client()
 | 
					            client = _default_client()
 | 
				
			||||||
        if None in (api_key, email):
 | 
					        if None in (api_key, email):
 | 
				
			||||||
            if config_file is None:
 | 
					            if config_file is None:
 | 
				
			||||||
                config_file = os.path.join(os.environ["HOME"], ".zuliprc")
 | 
					                config_file = get_default_config_filename()
 | 
				
			||||||
                if (not os.path.exists(config_file) and
 | 
					 | 
				
			||||||
                    os.path.exists(os.path.join(os.environ["HOME"], ".humbugrc"))):
 | 
					 | 
				
			||||||
                    raise RuntimeError("The Zulip API configuration file is now ~/.zuliprc; please run:\n\n  mv ~/.humbugrc ~/.zuliprc\n")
 | 
					 | 
				
			||||||
            if not os.path.exists(config_file):
 | 
					            if not os.path.exists(config_file):
 | 
				
			||||||
                raise RuntimeError("api_key or email not specified and %s does not exist"
 | 
					                raise RuntimeError("api_key or email not specified and %s does not exist"
 | 
				
			||||||
                                   % (config_file,))
 | 
					                                   % (config_file,))
 | 
				
			||||||
@@ -123,8 +176,15 @@ class Client(object):
 | 
				
			|||||||
        self.client_name = client
 | 
					        self.client_name = client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_user_agent(self):
 | 
					    def get_user_agent(self):
 | 
				
			||||||
 | 
					        vendor = ''
 | 
				
			||||||
 | 
					        vendor_version = ''
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
            vendor = platform.system()
 | 
					            vendor = platform.system()
 | 
				
			||||||
            vendor_version = platform.release()
 | 
					            vendor_version = platform.release()
 | 
				
			||||||
 | 
					        except IOError:
 | 
				
			||||||
 | 
					            # If the calling process is handling SIGCHLD, platform.system() can
 | 
				
			||||||
 | 
					            # fail with an IOError.  See http://bugs.python.org/issue9127
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if vendor == "Linux":
 | 
					        if vendor == "Linux":
 | 
				
			||||||
            vendor, vendor_version, dummy = platform.linux_distribution()
 | 
					            vendor, vendor_version, dummy = platform.linux_distribution()
 | 
				
			||||||
@@ -241,12 +301,16 @@ class Client(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def _register(cls, name, url=None, make_request=(lambda request={}: request),
 | 
					    def _register(cls, name, url=None, make_request=(lambda request={}: request),
 | 
				
			||||||
            method="POST", **query_kwargs):
 | 
					                  method="POST", computed_url=None, **query_kwargs):
 | 
				
			||||||
        if url is None:
 | 
					        if url is None:
 | 
				
			||||||
            url = name
 | 
					            url = name
 | 
				
			||||||
        def call(self, *args, **kwargs):
 | 
					        def call(self, *args, **kwargs):
 | 
				
			||||||
            request = make_request(*args, **kwargs)
 | 
					            request = make_request(*args, **kwargs)
 | 
				
			||||||
            return self.do_api_query(request, API_VERSTRING + url, method=method, **query_kwargs)
 | 
					            if computed_url is not None:
 | 
				
			||||||
 | 
					                req_url = computed_url(request)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                req_url = url
 | 
				
			||||||
 | 
					            return self.do_api_query(request, API_VERSTRING + req_url, method=method, **query_kwargs)
 | 
				
			||||||
        call.func_name = name
 | 
					        call.func_name = name
 | 
				
			||||||
        setattr(cls, name, call)
 | 
					        setattr(cls, name, call)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -352,6 +416,7 @@ Client._register('update_message', method='PATCH', url='messages', make_request=
 | 
				
			|||||||
Client._register('get_messages', method='GET', url='messages/latest', longpolling=True)
 | 
					Client._register('get_messages', method='GET', url='messages/latest', longpolling=True)
 | 
				
			||||||
Client._register('get_events', url='events', method='GET', longpolling=True, make_request=(lambda **kwargs: kwargs))
 | 
					Client._register('get_events', url='events', method='GET', longpolling=True, make_request=(lambda **kwargs: kwargs))
 | 
				
			||||||
Client._register('register', make_request=_mk_events)
 | 
					Client._register('register', make_request=_mk_events)
 | 
				
			||||||
 | 
					Client._register('export', method='GET', url='export')
 | 
				
			||||||
Client._register('deregister', url="events", method="DELETE", make_request=_mk_deregister)
 | 
					Client._register('deregister', url="events", method="DELETE", make_request=_mk_deregister)
 | 
				
			||||||
Client._register('get_profile', method='GET', url='users/me')
 | 
					Client._register('get_profile', method='GET', url='users/me')
 | 
				
			||||||
Client._register('get_streams', method='GET', url='streams', make_request=_kwargs_to_dict)
 | 
					Client._register('get_streams', method='GET', url='streams', make_request=_kwargs_to_dict)
 | 
				
			||||||
@@ -359,5 +424,8 @@ Client._register('get_members', method='GET', url='users')
 | 
				
			|||||||
Client._register('list_subscriptions', method='GET', url='users/me/subscriptions')
 | 
					Client._register('list_subscriptions', method='GET', url='users/me/subscriptions')
 | 
				
			||||||
Client._register('add_subscriptions', url='users/me/subscriptions', make_request=_mk_subs)
 | 
					Client._register('add_subscriptions', url='users/me/subscriptions', make_request=_mk_subs)
 | 
				
			||||||
Client._register('remove_subscriptions', method='PATCH', url='users/me/subscriptions', make_request=_mk_rm_subs)
 | 
					Client._register('remove_subscriptions', method='PATCH', url='users/me/subscriptions', make_request=_mk_rm_subs)
 | 
				
			||||||
 | 
					Client._register('get_subscribers', method='GET',
 | 
				
			||||||
 | 
					                 computed_url=lambda request: 'streams/%s/members' % (urllib.quote(request['stream'], safe=''),),
 | 
				
			||||||
 | 
					                 make_request=_kwargs_to_dict)
 | 
				
			||||||
Client._register('render_message', method='GET', url='messages/render')
 | 
					Client._register('render_message', method='GET', url='messages/render')
 | 
				
			||||||
Client._register('create_user', method='POST', url='users')
 | 
					Client._register('create_user', method='POST', url='users')
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										202
									
								
								assets/zulip-emoji/NOTICE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								assets/zulip-emoji/NOTICE
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					                                 Apache License
 | 
				
			||||||
 | 
					                           Version 2.0, January 2004
 | 
				
			||||||
 | 
					                        http://www.apache.org/licenses/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   1. Definitions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "License" shall mean the terms and conditions for use, reproduction,
 | 
				
			||||||
 | 
					      and distribution as defined by Sections 1 through 9 of this document.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Licensor" shall mean the copyright owner or entity authorized by
 | 
				
			||||||
 | 
					      the copyright owner that is granting the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Legal Entity" shall mean the union of the acting entity and all
 | 
				
			||||||
 | 
					      other entities that control, are controlled by, or are under common
 | 
				
			||||||
 | 
					      control with that entity. For the purposes of this definition,
 | 
				
			||||||
 | 
					      "control" means (i) the power, direct or indirect, to cause the
 | 
				
			||||||
 | 
					      direction or management of such entity, whether by contract or
 | 
				
			||||||
 | 
					      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
				
			||||||
 | 
					      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "You" (or "Your") shall mean an individual or Legal Entity
 | 
				
			||||||
 | 
					      exercising permissions granted by this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Source" form shall mean the preferred form for making modifications,
 | 
				
			||||||
 | 
					      including but not limited to software source code, documentation
 | 
				
			||||||
 | 
					      source, and configuration files.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Object" form shall mean any form resulting from mechanical
 | 
				
			||||||
 | 
					      transformation or translation of a Source form, including but
 | 
				
			||||||
 | 
					      not limited to compiled object code, generated documentation,
 | 
				
			||||||
 | 
					      and conversions to other media types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Work" shall mean the work of authorship, whether in Source or
 | 
				
			||||||
 | 
					      Object form, made available under the License, as indicated by a
 | 
				
			||||||
 | 
					      copyright notice that is included in or attached to the work
 | 
				
			||||||
 | 
					      (an example is provided in the Appendix below).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Derivative Works" shall mean any work, whether in Source or Object
 | 
				
			||||||
 | 
					      form, that is based on (or derived from) the Work and for which the
 | 
				
			||||||
 | 
					      editorial revisions, annotations, elaborations, or other modifications
 | 
				
			||||||
 | 
					      represent, as a whole, an original work of authorship. For the purposes
 | 
				
			||||||
 | 
					      of this License, Derivative Works shall not include works that remain
 | 
				
			||||||
 | 
					      separable from, or merely link (or bind by name) to the interfaces of,
 | 
				
			||||||
 | 
					      the Work and Derivative Works thereof.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Contribution" shall mean any work of authorship, including
 | 
				
			||||||
 | 
					      the original version of the Work and any modifications or additions
 | 
				
			||||||
 | 
					      to that Work or Derivative Works thereof, that is intentionally
 | 
				
			||||||
 | 
					      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
				
			||||||
 | 
					      or by an individual or Legal Entity authorized to submit on behalf of
 | 
				
			||||||
 | 
					      the copyright owner. For the purposes of this definition, "submitted"
 | 
				
			||||||
 | 
					      means any form of electronic, verbal, or written communication sent
 | 
				
			||||||
 | 
					      to the Licensor or its representatives, including but not limited to
 | 
				
			||||||
 | 
					      communication on electronic mailing lists, source code control systems,
 | 
				
			||||||
 | 
					      and issue tracking systems that are managed by, or on behalf of, the
 | 
				
			||||||
 | 
					      Licensor for the purpose of discussing and improving the Work, but
 | 
				
			||||||
 | 
					      excluding communication that is conspicuously marked or otherwise
 | 
				
			||||||
 | 
					      designated in writing by the copyright owner as "Not a Contribution."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
				
			||||||
 | 
					      on behalf of whom a Contribution has been received by Licensor and
 | 
				
			||||||
 | 
					      subsequently incorporated within the Work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
				
			||||||
 | 
					      this License, each Contributor hereby grants to You a perpetual,
 | 
				
			||||||
 | 
					      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
				
			||||||
 | 
					      copyright license to reproduce, prepare Derivative Works of,
 | 
				
			||||||
 | 
					      publicly display, publicly perform, sublicense, and distribute the
 | 
				
			||||||
 | 
					      Work and such Derivative Works in Source or Object form.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   3. Grant of Patent License. Subject to the terms and conditions of
 | 
				
			||||||
 | 
					      this License, each Contributor hereby grants to You a perpetual,
 | 
				
			||||||
 | 
					      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
				
			||||||
 | 
					      (except as stated in this section) patent license to make, have made,
 | 
				
			||||||
 | 
					      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
				
			||||||
 | 
					      where such license applies only to those patent claims licensable
 | 
				
			||||||
 | 
					      by such Contributor that are necessarily infringed by their
 | 
				
			||||||
 | 
					      Contribution(s) alone or by combination of their Contribution(s)
 | 
				
			||||||
 | 
					      with the Work to which such Contribution(s) was submitted. If You
 | 
				
			||||||
 | 
					      institute patent litigation against any entity (including a
 | 
				
			||||||
 | 
					      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
				
			||||||
 | 
					      or a Contribution incorporated within the Work constitutes direct
 | 
				
			||||||
 | 
					      or contributory patent infringement, then any patent licenses
 | 
				
			||||||
 | 
					      granted to You under this License for that Work shall terminate
 | 
				
			||||||
 | 
					      as of the date such litigation is filed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   4. Redistribution. You may reproduce and distribute copies of the
 | 
				
			||||||
 | 
					      Work or Derivative Works thereof in any medium, with or without
 | 
				
			||||||
 | 
					      modifications, and in Source or Object form, provided that You
 | 
				
			||||||
 | 
					      meet the following conditions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (a) You must give any other recipients of the Work or
 | 
				
			||||||
 | 
					          Derivative Works a copy of this License; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (b) You must cause any modified files to carry prominent notices
 | 
				
			||||||
 | 
					          stating that You changed the files; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (c) You must retain, in the Source form of any Derivative Works
 | 
				
			||||||
 | 
					          that You distribute, all copyright, patent, trademark, and
 | 
				
			||||||
 | 
					          attribution notices from the Source form of the Work,
 | 
				
			||||||
 | 
					          excluding those notices that do not pertain to any part of
 | 
				
			||||||
 | 
					          the Derivative Works; and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      (d) If the Work includes a "NOTICE" text file as part of its
 | 
				
			||||||
 | 
					          distribution, then any Derivative Works that You distribute must
 | 
				
			||||||
 | 
					          include a readable copy of the attribution notices contained
 | 
				
			||||||
 | 
					          within such NOTICE file, excluding those notices that do not
 | 
				
			||||||
 | 
					          pertain to any part of the Derivative Works, in at least one
 | 
				
			||||||
 | 
					          of the following places: within a NOTICE text file distributed
 | 
				
			||||||
 | 
					          as part of the Derivative Works; within the Source form or
 | 
				
			||||||
 | 
					          documentation, if provided along with the Derivative Works; or,
 | 
				
			||||||
 | 
					          within a display generated by the Derivative Works, if and
 | 
				
			||||||
 | 
					          wherever such third-party notices normally appear. The contents
 | 
				
			||||||
 | 
					          of the NOTICE file are for informational purposes only and
 | 
				
			||||||
 | 
					          do not modify the License. You may add Your own attribution
 | 
				
			||||||
 | 
					          notices within Derivative Works that You distribute, alongside
 | 
				
			||||||
 | 
					          or as an addendum to the NOTICE text from the Work, provided
 | 
				
			||||||
 | 
					          that such additional attribution notices cannot be construed
 | 
				
			||||||
 | 
					          as modifying the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      You may add Your own copyright statement to Your modifications and
 | 
				
			||||||
 | 
					      may provide additional or different license terms and conditions
 | 
				
			||||||
 | 
					      for use, reproduction, or distribution of Your modifications, or
 | 
				
			||||||
 | 
					      for any such Derivative Works as a whole, provided Your use,
 | 
				
			||||||
 | 
					      reproduction, and distribution of the Work otherwise complies with
 | 
				
			||||||
 | 
					      the conditions stated in this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
				
			||||||
 | 
					      any Contribution intentionally submitted for inclusion in the Work
 | 
				
			||||||
 | 
					      by You to the Licensor shall be under the terms and conditions of
 | 
				
			||||||
 | 
					      this License, without any additional terms or conditions.
 | 
				
			||||||
 | 
					      Notwithstanding the above, nothing herein shall supersede or modify
 | 
				
			||||||
 | 
					      the terms of any separate license agreement you may have executed
 | 
				
			||||||
 | 
					      with Licensor regarding such Contributions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   6. Trademarks. This License does not grant permission to use the trade
 | 
				
			||||||
 | 
					      names, trademarks, service marks, or product names of the Licensor,
 | 
				
			||||||
 | 
					      except as required for reasonable and customary use in describing the
 | 
				
			||||||
 | 
					      origin of the Work and reproducing the content of the NOTICE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
				
			||||||
 | 
					      agreed to in writing, Licensor provides the Work (and each
 | 
				
			||||||
 | 
					      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
				
			||||||
 | 
					      implied, including, without limitation, any warranties or conditions
 | 
				
			||||||
 | 
					      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
				
			||||||
 | 
					      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
				
			||||||
 | 
					      appropriateness of using or redistributing the Work and assume any
 | 
				
			||||||
 | 
					      risks associated with Your exercise of permissions under this License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   8. Limitation of Liability. In no event and under no legal theory,
 | 
				
			||||||
 | 
					      whether in tort (including negligence), contract, or otherwise,
 | 
				
			||||||
 | 
					      unless required by applicable law (such as deliberate and grossly
 | 
				
			||||||
 | 
					      negligent acts) or agreed to in writing, shall any Contributor be
 | 
				
			||||||
 | 
					      liable to You for damages, including any direct, indirect, special,
 | 
				
			||||||
 | 
					      incidental, or consequential damages of any character arising as a
 | 
				
			||||||
 | 
					      result of this License or out of the use or inability to use the
 | 
				
			||||||
 | 
					      Work (including but not limited to damages for loss of goodwill,
 | 
				
			||||||
 | 
					      work stoppage, computer failure or malfunction, or any and all
 | 
				
			||||||
 | 
					      other commercial damages or losses), even if such Contributor
 | 
				
			||||||
 | 
					      has been advised of the possibility of such damages.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   9. Accepting Warranty or Additional Liability. While redistributing
 | 
				
			||||||
 | 
					      the Work or Derivative Works thereof, You may choose to offer,
 | 
				
			||||||
 | 
					      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
				
			||||||
 | 
					      or other liability obligations and/or rights consistent with this
 | 
				
			||||||
 | 
					      License. However, in accepting such obligations, You may act only
 | 
				
			||||||
 | 
					      on Your own behalf and on Your sole responsibility, not on behalf
 | 
				
			||||||
 | 
					      of any other Contributor, and only if You agree to indemnify,
 | 
				
			||||||
 | 
					      defend, and hold each Contributor harmless for any liability
 | 
				
			||||||
 | 
					      incurred by, or claims asserted against, such Contributor by reason
 | 
				
			||||||
 | 
					      of your accepting any such warranty or additional liability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   END OF TERMS AND CONDITIONS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   APPENDIX: How to apply the Apache License to your work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      To apply the Apache License to your work, attach the following
 | 
				
			||||||
 | 
					      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
				
			||||||
 | 
					      replaced with your own identifying information. (Don't include
 | 
				
			||||||
 | 
					      the brackets!)  The text should be enclosed in the appropriate
 | 
				
			||||||
 | 
					      comment syntax for the file format. We also recommend that a
 | 
				
			||||||
 | 
					      file or class name and description of purpose be included on the
 | 
				
			||||||
 | 
					      same "printed page" as the copyright notice for easier
 | 
				
			||||||
 | 
					      identification within third-party archives.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Copyright [yyyy] [name of copyright owner]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					   you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					   You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					       http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					   distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					   See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					   limitations under the License.
 | 
				
			||||||
							
								
								
									
										13
									
								
								assets/zulip-emoji/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								assets/zulip-emoji/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					This directory contains images adapted from the Noto project. For more detail
 | 
				
			||||||
 | 
					about Noto, please refer to:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					https://code.google.com/p/noto/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These images were generated from the git repository at
 | 
				
			||||||
 | 
					<https://android.googlesource.com/platform/external/noto-fonts> as of
 | 
				
			||||||
 | 
					90372d894b5d9c9f2a111315d2eb3b8de1979ee4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<https://android.googlesource.com/platform/frameworks/base> at
 | 
				
			||||||
 | 
					07912f876c8639f811b06831465c14c4a3b17663.
 | 
				
			||||||
| 
		 Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB  | 
@@ -11,5 +11,5 @@ ZULIP_DIR=/home/zulip/deployments/current
 | 
				
			|||||||
STATE_DIR=/var/lib/nagios_state
 | 
					STATE_DIR=/var/lib/nagios_state
 | 
				
			||||||
STATE_FILE=$STATE_DIR/check-rabbitmq-consumers-$queue
 | 
					STATE_FILE=$STATE_DIR/check-rabbitmq-consumers-$queue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$ZULIP_DIR/bots/check-rabbitmq-consumers --queue=$queue &> ${STATE_FILE}-tmp;
 | 
					"$ZULIP_DIR/bots/check-rabbitmq-consumers" "--queue=$queue" &> "${STATE_FILE}-tmp";
 | 
				
			||||||
mv ${STATE_FILE}-tmp $STATE_FILE
 | 
					mv "${STATE_FILE}-tmp" "$STATE_FILE"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,14 @@ import time
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import subprocess
 | 
					import subprocess
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WARN_THRESHOLD = 10
 | 
					WARN_THRESHOLD_DEFAULT = 10
 | 
				
			||||||
CRIT_THRESHOLD = 50
 | 
					WARN_THRESHOLD = {
 | 
				
			||||||
 | 
					    'missedmessage_emails': 45,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					CRIT_THRESHOLD_DEFAULT = 50
 | 
				
			||||||
 | 
					CRIT_THRESHOLD = {
 | 
				
			||||||
 | 
					    'missedmessage_emails': 70,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
states = {
 | 
					states = {
 | 
				
			||||||
    0: "OK",
 | 
					    0: "OK",
 | 
				
			||||||
@@ -33,10 +39,10 @@ for line in output.split("\n"):
 | 
				
			|||||||
        queue = m.group(1)
 | 
					        queue = m.group(1)
 | 
				
			||||||
        count = int(m.group(2))
 | 
					        count = int(m.group(2))
 | 
				
			||||||
        this_status = 0
 | 
					        this_status = 0
 | 
				
			||||||
        if count > CRIT_THRESHOLD:
 | 
					        if count > CRIT_THRESHOLD.get(queue, CRIT_THRESHOLD_DEFAULT):
 | 
				
			||||||
            this_status = 2
 | 
					            this_status = 2
 | 
				
			||||||
            warn_queues.append(queue)
 | 
					            warn_queues.append(queue)
 | 
				
			||||||
        elif count > WARN_THRESHOLD:
 | 
					        elif count > WARN_THRESHOLD.get(queue, WARN_THRESHOLD_DEFAULT):
 | 
				
			||||||
            this_status = max(status, 1)
 | 
					            this_status = max(status, 1)
 | 
				
			||||||
            warn_queues.append(queue)
 | 
					            warn_queues.append(queue)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,7 +56,7 @@ now_struct = time.gmtime(now)
 | 
				
			|||||||
# While we are sending digest emails, at 11am each weekday, the mail queues can
 | 
					# While we are sending digest emails, at 11am each weekday, the mail queues can
 | 
				
			||||||
# get backed up; don't alert on those.
 | 
					# get backed up; don't alert on those.
 | 
				
			||||||
if not set(warn_queues) - set(("missedmessage_emails", "digest_emails")) and \
 | 
					if not set(warn_queues) - set(("missedmessage_emails", "digest_emails")) and \
 | 
				
			||||||
        now_struct.tm_hour == 16 and now_struct.tm_min < 15:
 | 
					        now_struct.tm_hour == 15 and now_struct.tm_min < 25:
 | 
				
			||||||
    status = 0
 | 
					    status = 0
 | 
				
			||||||
    print("%s|%s|%s|processing digests, not alerting on elevated mail queues" % (
 | 
					    print("%s|%s|%s|processing digests, not alerting on elevated mail queues" % (
 | 
				
			||||||
            now, status, states[status]))
 | 
					            now, status, states[status]))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,7 +47,7 @@ parser.add_option_group(zulip.generate_option_group(parser))
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
(options, args) = parser.parse_args()
 | 
					(options, args) = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if not (options.user and options.calendar):
 | 
					if not (options.zulip_email and options.calendar):
 | 
				
			||||||
    parser.error('You must specify --user and --calendar')
 | 
					    parser.error('You must specify --user and --calendar')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
try:
 | 
					try:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,9 +12,11 @@ from irc.client import ip_numstr_to_quad, ip_quad_to_numstr
 | 
				
			|||||||
import zulip
 | 
					import zulip
 | 
				
			||||||
import optparse
 | 
					import optparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IRC_DOMAIN = "irc.example.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def zulip_sender(sender_string):
 | 
					def zulip_sender(sender_string):
 | 
				
			||||||
    nick = sender_string.split("!")[0]
 | 
					    nick = sender_string.split("!")[0]
 | 
				
			||||||
    return nick + "@irc.zulip.com"
 | 
					    return nick + "@" + IRC_DOMAIN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IRCBot(irc.bot.SingleServerIRCBot):
 | 
					class IRCBot(irc.bot.SingleServerIRCBot):
 | 
				
			||||||
    def __init__(self, channel, nickname, server, port=6667):
 | 
					    def __init__(self, channel, nickname, server, port=6667):
 | 
				
			||||||
@@ -47,14 +49,14 @@ class IRCBot(irc.bot.SingleServerIRCBot):
 | 
				
			|||||||
    def on_privmsg(self, c, e):
 | 
					    def on_privmsg(self, c, e):
 | 
				
			||||||
        content = e.arguments[0]
 | 
					        content = e.arguments[0]
 | 
				
			||||||
        sender = zulip_sender(e.source)
 | 
					        sender = zulip_sender(e.source)
 | 
				
			||||||
        if sender.endswith("_zulip@irc.zulip.com"):
 | 
					        if sender.endswith("_zulip@" + IRC_DOMAIN):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Forward the PM to Zulip
 | 
					        # Forward the PM to Zulip
 | 
				
			||||||
        print zulip_client.send_message({
 | 
					        print zulip_client.send_message({
 | 
				
			||||||
                "sender": sender,
 | 
					                "sender": sender,
 | 
				
			||||||
                "type": "private",
 | 
					                "type": "private",
 | 
				
			||||||
                "to": "tabbott@zulip.com",
 | 
					                "to": "username@example.com",
 | 
				
			||||||
                "content": content,
 | 
					                "content": content,
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,7 +64,7 @@ class IRCBot(irc.bot.SingleServerIRCBot):
 | 
				
			|||||||
        content = e.arguments[0]
 | 
					        content = e.arguments[0]
 | 
				
			||||||
        stream = e.target
 | 
					        stream = e.target
 | 
				
			||||||
        sender = zulip_sender(e.source)
 | 
					        sender = zulip_sender(e.source)
 | 
				
			||||||
        if sender.endswith("_zulip@irc.zulip.com"):
 | 
					        if sender.endswith("_zulip@" + IRC_DOMAIN):
 | 
				
			||||||
            return
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Forward the stream message to Zulip
 | 
					        # Forward the stream message to Zulip
 | 
				
			||||||
@@ -94,8 +96,8 @@ usage = """python irc-mirror.py --server=IRC_SERVER --channel=<CHANNEL> --nick-p
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Example:
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
python irc-mirror.py --irc-server=127.0.0.1 --channel='#test' --nick-prefix=tabbott
 | 
					python irc-mirror.py --irc-server=127.0.0.1 --channel='#test' --nick-prefix=username
 | 
				
			||||||
  --site=https://staging.zulip.com --user=irc-bot@zulip.com
 | 
					  --site=https://zulip.example.com --user=irc-bot@example.com
 | 
				
			||||||
  --api-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 | 
					  --api-key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note that "_zulip" will be automatically appended to the IRC nick provided
 | 
					Note that "_zulip" will be automatically appended to the IRC nick provided
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										59
									
								
								bots/jabber_mirror.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										59
									
								
								bots/jabber_mirror.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					# Copyright (C) 2014 Zulip, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Permission is hereby granted, free of charge, to any person
 | 
				
			||||||
 | 
					# obtaining a copy of this software and associated documentation files
 | 
				
			||||||
 | 
					# (the "Software"), to deal in the Software without restriction,
 | 
				
			||||||
 | 
					# including without limitation the rights to use, copy, modify, merge,
 | 
				
			||||||
 | 
					# publish, distribute, sublicense, and/or sell copies of the Software,
 | 
				
			||||||
 | 
					# and to permit persons to whom the Software is furnished to do so,
 | 
				
			||||||
 | 
					# subject to the following conditions:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The above copyright notice and this permission notice shall be
 | 
				
			||||||
 | 
					# included in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
				
			||||||
 | 
					# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
				
			||||||
 | 
					# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					# SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import traceback
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
 | 
					from zulip import RandomExponentialBackoff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def die(signal, frame):
 | 
				
			||||||
 | 
					    # We actually want to exit, so run os._exit (so as not to be caught and restarted)
 | 
				
			||||||
 | 
					    os._exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signal.signal(signal.SIGINT, die)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					args = [os.path.join(os.path.dirname(sys.argv[0]), "jabber_mirror_backend.py")]
 | 
				
			||||||
 | 
					args.extend(sys.argv[1:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					backoff = RandomExponentialBackoff(timeout_success_equivalent=300)
 | 
				
			||||||
 | 
					while backoff.keep_going():
 | 
				
			||||||
 | 
					    print "Starting Jabber mirroring bot"
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        ret = subprocess.call(args)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        traceback.print_exc()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        if ret == 2:
 | 
				
			||||||
 | 
					            # Don't try again on initial configuration errors
 | 
				
			||||||
 | 
					            sys.exit(ret)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    backoff.fail()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print ""
 | 
				
			||||||
 | 
					print ""
 | 
				
			||||||
 | 
					print "ERROR: The Jabber mirroring bot is unable to continue mirroring Jabber."
 | 
				
			||||||
 | 
					print "Please contact support@zulip.com if you need assistance."
 | 
				
			||||||
 | 
					print ""
 | 
				
			||||||
 | 
					sys.exit(1)
 | 
				
			||||||
							
								
								
									
										445
									
								
								bots/jabber_mirror_backend.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										445
									
								
								bots/jabber_mirror_backend.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,445 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/python
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (C) 2013 Permabit, Inc.
 | 
				
			||||||
 | 
					# Copyright (C) 2013--2014 Zulip, Inc.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Permission is hereby granted, free of charge, to any person
 | 
				
			||||||
 | 
					# obtaining a copy of this software and associated documentation files
 | 
				
			||||||
 | 
					# (the "Software"), to deal in the Software without restriction,
 | 
				
			||||||
 | 
					# including without limitation the rights to use, copy, modify, merge,
 | 
				
			||||||
 | 
					# publish, distribute, sublicense, and/or sell copies of the Software,
 | 
				
			||||||
 | 
					# and to permit persons to whom the Software is furnished to do so,
 | 
				
			||||||
 | 
					# subject to the following conditions:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The above copyright notice and this permission notice shall be
 | 
				
			||||||
 | 
					# included in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
				
			||||||
 | 
					# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
				
			||||||
 | 
					# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					# SOFTWARE.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The following is a table showing which kinds of messages are handled by the
 | 
				
			||||||
 | 
					# mirror in each mode:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     Message origin/type --> |  Jabber  |   Zulip
 | 
				
			||||||
 | 
					#  Mode/sender-,              +-----+----+--------+----
 | 
				
			||||||
 | 
					#              V              | MUC | PM | stream | PM
 | 
				
			||||||
 | 
					# --------------+-------------+-----+----+--------+----
 | 
				
			||||||
 | 
					#               | other sender|     | x  |        |
 | 
				
			||||||
 | 
					# personal mode +-------------+-----+----+--------+----
 | 
				
			||||||
 | 
					#               | self sender |     | x  |   x    | x
 | 
				
			||||||
 | 
					# ------------- +-------------+-----+----+--------+----
 | 
				
			||||||
 | 
					#               | other sender|  x  |    |        |
 | 
				
			||||||
 | 
					# public mode   +-------------+-----+----+--------+----
 | 
				
			||||||
 | 
					#               | self sender |     |    |        |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import threading
 | 
				
			||||||
 | 
					import optparse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from sleekxmpp import ClientXMPP, InvalidJID, JID
 | 
				
			||||||
 | 
					from sleekxmpp.exceptions import IqError, IqTimeout
 | 
				
			||||||
 | 
					from ConfigParser import SafeConfigParser
 | 
				
			||||||
 | 
					import os, sys, zulip, getpass
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__version__ = "1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def room_to_stream(room):
 | 
				
			||||||
 | 
					    return room + "/xmpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def stream_to_room(stream):
 | 
				
			||||||
 | 
					    return stream.lower().rpartition("/xmpp")[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def jid_to_zulip(jid):
 | 
				
			||||||
 | 
					    suffix = ''
 | 
				
			||||||
 | 
					    if not jid.username.endswith("-bot"):
 | 
				
			||||||
 | 
					        suffix = options.zulip_email_suffix
 | 
				
			||||||
 | 
					    return "%s%s@%s" % (jid.username, suffix, options.zulip_domain)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def zulip_to_jid(email, jabber_domain):
 | 
				
			||||||
 | 
					    jid = JID(email, domain=jabber_domain)
 | 
				
			||||||
 | 
					    if (options.zulip_email_suffix
 | 
				
			||||||
 | 
					        and options.zulip_email_suffix in jid.username
 | 
				
			||||||
 | 
					        and not jid.username.endswith("-bot")):
 | 
				
			||||||
 | 
					        jid.username = jid.username.rpartition(options.zulip_email_suffix)[0]
 | 
				
			||||||
 | 
					    return jid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class JabberToZulipBot(ClientXMPP):
 | 
				
			||||||
 | 
					    def __init__(self, jid, password, rooms):
 | 
				
			||||||
 | 
					        if jid.resource:
 | 
				
			||||||
 | 
					            self.nick = jid.resource
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.nick = jid.username
 | 
				
			||||||
 | 
					            jid.resource = "zulip"
 | 
				
			||||||
 | 
					        ClientXMPP.__init__(self, jid, password)
 | 
				
			||||||
 | 
					        self.rooms = set()
 | 
				
			||||||
 | 
					        self.rooms_to_join = rooms
 | 
				
			||||||
 | 
					        self.add_event_handler("session_start", self.session_start)
 | 
				
			||||||
 | 
					        self.add_event_handler("message", self.message)
 | 
				
			||||||
 | 
					        self.zulip = None
 | 
				
			||||||
 | 
					        self.use_ipv6 = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.register_plugin('xep_0045') # Jabber chatrooms
 | 
				
			||||||
 | 
					        self.register_plugin('xep_0199') # XMPP Ping
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_zulip_client(self, client):
 | 
				
			||||||
 | 
					        self.zulip = client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def session_start(self, event):
 | 
				
			||||||
 | 
					        self.get_roster()
 | 
				
			||||||
 | 
					        self.send_presence()
 | 
				
			||||||
 | 
					        for room in self.rooms_to_join:
 | 
				
			||||||
 | 
					            self.join_muc(room)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def join_muc(self, room):
 | 
				
			||||||
 | 
					        if room in self.rooms:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        logging.debug("Joining " + room)
 | 
				
			||||||
 | 
					        self.rooms.add(room)
 | 
				
			||||||
 | 
					        muc_jid = JID(local=room, domain=options.conference_domain)
 | 
				
			||||||
 | 
					        xep0045 = self.plugin['xep_0045']
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            xep0045.joinMUC(muc_jid, self.nick, wait=True)
 | 
				
			||||||
 | 
					        except InvalidJID:
 | 
				
			||||||
 | 
					            logging.error("Could not join room: " + str(muc_jid))
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Configure the room.  Really, we should only do this if the room is
 | 
				
			||||||
 | 
					        # newly created.
 | 
				
			||||||
 | 
					        form = None
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            form = xep0045.getRoomConfig(muc_jid)
 | 
				
			||||||
 | 
					        except ValueError:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        if form:
 | 
				
			||||||
 | 
					            xep0045.configureRoom(muc_jid, form)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            logging.error("Could not configure room: " + str(muc_jid))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def leave_muc(self, room):
 | 
				
			||||||
 | 
					        if room not in self.rooms:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        logging.debug("Leaving " + room)
 | 
				
			||||||
 | 
					        self.rooms.remove(room)
 | 
				
			||||||
 | 
					        muc_jid = JID(local=room, domain=options.conference_domain)
 | 
				
			||||||
 | 
					        self.plugin['xep_0045'].leaveMUC(muc_jid, self.nick)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def message(self, msg):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if msg["type"] == "groupchat":
 | 
				
			||||||
 | 
					                return self.group(msg)
 | 
				
			||||||
 | 
					            elif msg["type"] == "chat":
 | 
				
			||||||
 | 
					                return self.private(msg)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                logging.warning("Got unexpected message type")
 | 
				
			||||||
 | 
					                logging.warning(msg)
 | 
				
			||||||
 | 
					        except Exception:
 | 
				
			||||||
 | 
					            logging.exception("Error forwarding Jabber => Zulip")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def private(self, msg):
 | 
				
			||||||
 | 
					        if options.mode == 'public' or msg['thread'] == u'\u1FFFE':
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        sender = jid_to_zulip(msg["from"])
 | 
				
			||||||
 | 
					        recipient = jid_to_zulip(msg["to"])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        zulip_message = dict(
 | 
				
			||||||
 | 
					            sender = sender,
 | 
				
			||||||
 | 
					            type = "private",
 | 
				
			||||||
 | 
					            to = recipient,
 | 
				
			||||||
 | 
					            content = msg["body"],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        ret = self.zulip.client.send_message(zulip_message)
 | 
				
			||||||
 | 
					        if ret.get("result") != "success":
 | 
				
			||||||
 | 
					            logging.error(ret)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def group(self, msg):
 | 
				
			||||||
 | 
					        if options.mode == 'personal' or msg["thread"] == u'\u1FFFE':
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        subject = msg["subject"]
 | 
				
			||||||
 | 
					        if len(subject) == 0:
 | 
				
			||||||
 | 
					            subject = "(no topic)"
 | 
				
			||||||
 | 
					        stream = room_to_stream(msg['from'].local)
 | 
				
			||||||
 | 
					        sender_nick = msg.get_mucnick()
 | 
				
			||||||
 | 
					        if not sender_nick:
 | 
				
			||||||
 | 
					            # Messages from the room itself have no nickname.  We should not try
 | 
				
			||||||
 | 
					            # to mirror these
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        jid = self.nickname_to_jid(msg.get_mucroom(), sender_nick)
 | 
				
			||||||
 | 
					        sender = jid_to_zulip(jid)
 | 
				
			||||||
 | 
					        zulip_message = dict(
 | 
				
			||||||
 | 
					            forged = "yes",
 | 
				
			||||||
 | 
					            sender = sender,
 | 
				
			||||||
 | 
					            type = "stream",
 | 
				
			||||||
 | 
					            subject = subject,
 | 
				
			||||||
 | 
					            to = stream,
 | 
				
			||||||
 | 
					            content = msg["body"],
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        ret = self.zulip.client.send_message(zulip_message)
 | 
				
			||||||
 | 
					        if ret.get("result") != "success":
 | 
				
			||||||
 | 
					            logging.error(ret)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def nickname_to_jid(self, room, nick):
 | 
				
			||||||
 | 
					        jid = self.plugin['xep_0045'].getJidProperty(room, nick, "jid")
 | 
				
			||||||
 | 
					        if (jid is None or jid == ''):
 | 
				
			||||||
 | 
					            return JID(local=nick.replace(' ', ''), domain=self.boundjid.domain)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return jid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ZulipToJabberBot(object):
 | 
				
			||||||
 | 
					    def __init__(self, zulip_client):
 | 
				
			||||||
 | 
					        self.client = zulip_client
 | 
				
			||||||
 | 
					        self.jabber = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def set_jabber_client(self, client):
 | 
				
			||||||
 | 
					        self.jabber = client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_event(self, event):
 | 
				
			||||||
 | 
					        if event['type'] == 'message':
 | 
				
			||||||
 | 
					            message = event["message"]
 | 
				
			||||||
 | 
					            if message['sender_email'] != self.client.email:
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                if message['type'] == 'stream':
 | 
				
			||||||
 | 
					                    self.stream_message(message)
 | 
				
			||||||
 | 
					                elif message['type'] == 'private':
 | 
				
			||||||
 | 
					                    self.private_message(message)
 | 
				
			||||||
 | 
					            except:
 | 
				
			||||||
 | 
					                logging.exception("Exception forwarding Zulip => Jabber")
 | 
				
			||||||
 | 
					        elif event['type'] == 'subscription':
 | 
				
			||||||
 | 
					            self.process_subscription(event)
 | 
				
			||||||
 | 
					        elif event['type'] == 'stream':
 | 
				
			||||||
 | 
					            self.process_stream(event)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stream_message(self, msg):
 | 
				
			||||||
 | 
					        stream = msg['display_recipient']
 | 
				
			||||||
 | 
					        if not stream.endswith("/xmpp"):
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        room = stream_to_room(stream)
 | 
				
			||||||
 | 
					        jabber_recipient = JID(local=room, domain=options.conference_domain)
 | 
				
			||||||
 | 
					        outgoing = self.jabber.make_message(
 | 
				
			||||||
 | 
					            mto   = jabber_recipient,
 | 
				
			||||||
 | 
					            mbody = msg['content'],
 | 
				
			||||||
 | 
					            mtype = 'groupchat')
 | 
				
			||||||
 | 
					        outgoing['thread'] = u'\u1FFFE'
 | 
				
			||||||
 | 
					        outgoing.send()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def private_message(self, msg):
 | 
				
			||||||
 | 
					        for recipient in msg['display_recipient']:
 | 
				
			||||||
 | 
					            if recipient["email"] == self.client.email:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            if not recipient["is_mirror_dummy"]:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            recip_email = recipient['email']
 | 
				
			||||||
 | 
					            jabber_recipient = zulip_to_jid(recip_email, self.jabber.boundjid.domain)
 | 
				
			||||||
 | 
					            outgoing = self.jabber.make_message(
 | 
				
			||||||
 | 
					                mto   = jabber_recipient,
 | 
				
			||||||
 | 
					                mbody = msg['content'],
 | 
				
			||||||
 | 
					                mtype = 'chat')
 | 
				
			||||||
 | 
					            outgoing['thread'] = u'\u1FFFE'
 | 
				
			||||||
 | 
					            outgoing.send()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_subscription(self, event):
 | 
				
			||||||
 | 
					        if event['op'] == 'add':
 | 
				
			||||||
 | 
					            streams = [s['name'].lower() for s in event['subscriptions']]
 | 
				
			||||||
 | 
					            streams = [s for s in streams if s.endswith("/xmpp")]
 | 
				
			||||||
 | 
					            for stream in streams:
 | 
				
			||||||
 | 
					                self.jabber.join_muc(stream_to_room(stream))
 | 
				
			||||||
 | 
					        if event['op'] == 'remove':
 | 
				
			||||||
 | 
					            streams = [s['name'].lower() for s in event['subscriptions']]
 | 
				
			||||||
 | 
					            streams = [s for s in streams if s.endswith("/xmpp")]
 | 
				
			||||||
 | 
					            for stream in streams:
 | 
				
			||||||
 | 
					                self.jabber.leave_muc(stream_to_room(stream))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def process_stream(self, event):
 | 
				
			||||||
 | 
					        if event['op'] == 'occupy':
 | 
				
			||||||
 | 
					            streams = [s['name'].lower() for s in event['streams']]
 | 
				
			||||||
 | 
					            streams = [s for s in streams if s.endswith("/xmpp")]
 | 
				
			||||||
 | 
					            for stream in streams:
 | 
				
			||||||
 | 
					                self.jabber.join_muc(stream_to_room(stream))
 | 
				
			||||||
 | 
					        if event['op'] == 'vacate':
 | 
				
			||||||
 | 
					            streams = [s['name'].lower() for s in event['streams']]
 | 
				
			||||||
 | 
					            streams = [s for s in streams if s.endswith("/xmpp")]
 | 
				
			||||||
 | 
					            for stream in streams:
 | 
				
			||||||
 | 
					                self.jabber.leave_muc(stream_to_room(stream))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_rooms(zulip):
 | 
				
			||||||
 | 
					    def get_stream_infos(key, method):
 | 
				
			||||||
 | 
					        ret = method()
 | 
				
			||||||
 | 
					        if ret.get("result") != "success":
 | 
				
			||||||
 | 
					            logging.error(ret)
 | 
				
			||||||
 | 
					            sys.exit("Could not get initial list of Zulip %s" % (key,))
 | 
				
			||||||
 | 
					        return ret[key]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.mode == 'public':
 | 
				
			||||||
 | 
					        stream_infos = get_stream_infos("streams", zulip.client.get_streams)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        stream_infos = get_stream_infos("subscriptions", zulip.client.list_subscriptions)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rooms = []
 | 
				
			||||||
 | 
					    for stream_info in stream_infos:
 | 
				
			||||||
 | 
					            stream = stream_info['name']
 | 
				
			||||||
 | 
					            if stream.endswith("/xmpp"):
 | 
				
			||||||
 | 
					                rooms.append(stream_to_room(stream))
 | 
				
			||||||
 | 
					    return rooms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def config_error(msg):
 | 
				
			||||||
 | 
					    sys.stderr.write("%s\n" % (msg,))
 | 
				
			||||||
 | 
					    sys.exit(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    parser = optparse.OptionParser(epilog=
 | 
				
			||||||
 | 
					'''Most general and Jabber configuration options may also be specified in the
 | 
				
			||||||
 | 
					zulip configuration file under the jabber_mirror section (exceptions are noted
 | 
				
			||||||
 | 
					in their help sections).  Keys have the same name as options with hyphens
 | 
				
			||||||
 | 
					replaced with underscores.  Zulip configuration options go in the api section,
 | 
				
			||||||
 | 
					as normal.'''.replace("\n", " ")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					    parser.add_option('--mode',
 | 
				
			||||||
 | 
					                      default=None,
 | 
				
			||||||
 | 
					                      action='store',
 | 
				
			||||||
 | 
					                      help= \
 | 
				
			||||||
 | 
					'''Which mode to run in.  Valid options are "personal" and "public".  In
 | 
				
			||||||
 | 
					"personal" mode, the mirror uses an individual users' credentials and mirrors
 | 
				
			||||||
 | 
					all messages they send on Zulip to Jabber and all private Jabber messages to
 | 
				
			||||||
 | 
					Zulip.  In "public" mode, the mirror uses the credentials for a dedicated mirror
 | 
				
			||||||
 | 
					user and mirrors messages sent to Jabber rooms to Zulip.  Defaults to
 | 
				
			||||||
 | 
					"personal"'''.replace("\n", " "))
 | 
				
			||||||
 | 
					    parser.add_option('--zulip-email-suffix',
 | 
				
			||||||
 | 
					                      default=None,
 | 
				
			||||||
 | 
					                      action='store',
 | 
				
			||||||
 | 
					                      help= \
 | 
				
			||||||
 | 
					'''Add the specified suffix to the local part of email addresses constructed
 | 
				
			||||||
 | 
					from JIDs and nicks before sending requests to the Zulip server, and remove the
 | 
				
			||||||
 | 
					suffix before sending requests to the Jabber server.  For example, specifying
 | 
				
			||||||
 | 
					"+foo" will cause messages that are sent to the "bar" room by nickname "qux" to
 | 
				
			||||||
 | 
					be mirrored to the "bar/xmpp" stream in Zulip by user "qux+foo@example.com". This
 | 
				
			||||||
 | 
					option does not affect login credentials.'''.replace("\n", " "))
 | 
				
			||||||
 | 
					    parser.add_option('-d', '--debug',
 | 
				
			||||||
 | 
					                      help='set logging to DEBUG.  Can not be set via config file.',
 | 
				
			||||||
 | 
					                      action='store_const',
 | 
				
			||||||
 | 
					                      dest='log_level',
 | 
				
			||||||
 | 
					                      const=logging.DEBUG,
 | 
				
			||||||
 | 
					                      default=logging.INFO)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jabber_group = optparse.OptionGroup(parser, "Jabber configuration")
 | 
				
			||||||
 | 
					    jabber_group.add_option('--jid',
 | 
				
			||||||
 | 
					                            default=None,
 | 
				
			||||||
 | 
					                            action='store',
 | 
				
			||||||
 | 
					                            help="Your Jabber JID.  If a resource is specified, "
 | 
				
			||||||
 | 
					                            + "it will be used as the nickname when joining MUCs.  "
 | 
				
			||||||
 | 
					                            + "Specifying the nickname is mostly useful if you want "
 | 
				
			||||||
 | 
					                            + "to run the public mirror from a regular user instead of "
 | 
				
			||||||
 | 
					                            + "from a dedicated account.")
 | 
				
			||||||
 | 
					    jabber_group.add_option('--jabber-password',
 | 
				
			||||||
 | 
					                            default=None,
 | 
				
			||||||
 | 
					                            action='store',
 | 
				
			||||||
 | 
					                            help="Your Jabber password")
 | 
				
			||||||
 | 
					    jabber_group.add_option('--conference-domain',
 | 
				
			||||||
 | 
					                            default=None,
 | 
				
			||||||
 | 
					                            action='store',
 | 
				
			||||||
 | 
					                            help="Your Jabber conference domain (E.g. conference.jabber.example.com).  "
 | 
				
			||||||
 | 
					                            + "If not specifed, \"conference.\" will be prepended to your JID's domain.")
 | 
				
			||||||
 | 
					    jabber_group.add_option('--no-use-tls',
 | 
				
			||||||
 | 
					                            default=None,
 | 
				
			||||||
 | 
					                            action='store_true')
 | 
				
			||||||
 | 
					    jabber_group.add_option('--jabber-server-address',
 | 
				
			||||||
 | 
					                            default=None,
 | 
				
			||||||
 | 
					                            action='store',
 | 
				
			||||||
 | 
					               help="The hostname of your Jabber server. This is only needed if "
 | 
				
			||||||
 | 
					                            "your server is missing SRV records")
 | 
				
			||||||
 | 
					    jabber_group.add_option('--jabber-server-port',
 | 
				
			||||||
 | 
					                            default='5222',
 | 
				
			||||||
 | 
					                            action='store',
 | 
				
			||||||
 | 
					               help="The port of your Jabber server. This is only needed if "
 | 
				
			||||||
 | 
					                            "your server is missing SRV records")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_option_group(jabber_group)
 | 
				
			||||||
 | 
					    parser.add_option_group(zulip.generate_option_group(parser, "zulip-"))
 | 
				
			||||||
 | 
					    (options, args) = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    logging.basicConfig(level=options.log_level,
 | 
				
			||||||
 | 
					                        format='%(levelname)-8s %(message)s')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.zulip_config_file is None:
 | 
				
			||||||
 | 
					        config_file = zulip.get_default_config_filename()
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        config_file = options.zulip_config_file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    config = SafeConfigParser()
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        with file(config_file, 'r') as f:
 | 
				
			||||||
 | 
					            config.readfp(f, config_file)
 | 
				
			||||||
 | 
					    except IOError:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    for option in ("jid", "jabber_password", "conference_domain", "mode", "zulip_email_suffix", "jabber_server_address", "jabber_server_port"):
 | 
				
			||||||
 | 
					        if (getattr(options, option) is None
 | 
				
			||||||
 | 
					            and config.has_option("jabber_mirror", option)):
 | 
				
			||||||
 | 
					            setattr(options, option, config.get("jabber_mirror", option))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for option in ("no_use_tls",):
 | 
				
			||||||
 | 
					        if getattr(options, option) is None:
 | 
				
			||||||
 | 
					            if config.has_option("jabber_mirror", option):
 | 
				
			||||||
 | 
					                setattr(options, option, config.getboolean("jabber_mirror", option))
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                setattr(options, option, False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.mode is None:
 | 
				
			||||||
 | 
					        options.mode = "personal"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.zulip_email_suffix is None:
 | 
				
			||||||
 | 
					        options.zulip_email_suffix = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.mode not in ('public', 'personal'):
 | 
				
			||||||
 | 
					        config_error("Bad value for --mode: must be one of 'public' or 'personal'")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if None in (options.jid, options.jabber_password):
 | 
				
			||||||
 | 
					        config_error("You must specify your Jabber JID and Jabber password either "
 | 
				
			||||||
 | 
					                     + "in the Zulip configuration file or on the commandline")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    zulip = ZulipToJabberBot(zulip.init_from_options(options, "JabberMirror/" + __version__))
 | 
				
			||||||
 | 
					    # This won't work for open realms that don't have a consistent domain
 | 
				
			||||||
 | 
					    options.zulip_domain = zulip.client.email.partition('@')[-1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        jid = JID(options.jid)
 | 
				
			||||||
 | 
					    except InvalidJID as e:
 | 
				
			||||||
 | 
					        config_error("Bad JID: %s: %s" % (options.jid, e.message))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.conference_domain is None:
 | 
				
			||||||
 | 
					        options.conference_domain = "conference.%s" % (jid.domain,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    xmpp = JabberToZulipBot(jid, options.jabber_password, get_rooms(zulip))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    address = None
 | 
				
			||||||
 | 
					    if options.jabber_server_address:
 | 
				
			||||||
 | 
					        address = (options.jabber_server_address, options.jabber_server_port)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not xmpp.connect(use_tls=not options.no_use_tls, address=address):
 | 
				
			||||||
 | 
					        sys.exit("Unable to connect to Jabber server")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    xmpp.set_zulip_client(zulip)
 | 
				
			||||||
 | 
					    zulip.set_jabber_client(xmpp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    xmpp.process(block=False)
 | 
				
			||||||
 | 
					    if options.mode == 'public':
 | 
				
			||||||
 | 
					        event_types = ['stream']
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        event_types = ['message', 'subscription']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        logging.info("Connecting to Zulip.")
 | 
				
			||||||
 | 
					        zulip.client.call_on_each_event(zulip.process_event,
 | 
				
			||||||
 | 
					                                        event_types=event_types)
 | 
				
			||||||
 | 
					    except BaseException as e:
 | 
				
			||||||
 | 
					        logging.exception("Exception in main loop")
 | 
				
			||||||
 | 
					        xmpp.abort()
 | 
				
			||||||
 | 
					        sys.exit(1)
 | 
				
			||||||
@@ -28,7 +28,6 @@ import traceback
 | 
				
			|||||||
import signal
 | 
					import signal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from zephyr_mirror_backend import parse_args
 | 
					from zephyr_mirror_backend import parse_args
 | 
				
			||||||
from zephyr_mirror_backend import RandomExponentialBackoff
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def die(signal, frame):
 | 
					def die(signal, frame):
 | 
				
			||||||
    # We actually want to exit, so run os._exit (so as not to be caught and restarted)
 | 
					    # We actually want to exit, so run os._exit (so as not to be caught and restarted)
 | 
				
			||||||
@@ -38,6 +37,9 @@ signal.signal(signal.SIGINT, die)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
(options, args) = parse_args()
 | 
					(options, args) = parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sys.path[:0] = [os.path.join(options.root_path, 'api')]
 | 
				
			||||||
 | 
					from zulip import RandomExponentialBackoff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
args = [os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py")]
 | 
					args = [os.path.join(options.root_path, "user_root", "zephyr_mirror_backend.py")]
 | 
				
			||||||
args.extend(sys.argv[1:])
 | 
					args.extend(sys.argv[1:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -60,7 +62,7 @@ if options.forward_class_messages and not options.noshard:
 | 
				
			|||||||
        pass
 | 
					        pass
 | 
				
			||||||
    sys.exit(0)
 | 
					    sys.exit(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
backoff = RandomExponentialBackoff()
 | 
					backoff = RandomExponentialBackoff(timeout_success_equivalent=300)
 | 
				
			||||||
while backoff.keep_going():
 | 
					while backoff.keep_going():
 | 
				
			||||||
    print "Starting zephyr mirroring bot"
 | 
					    print "Starting zephyr mirroring bot"
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,39 +37,8 @@ import signal
 | 
				
			|||||||
import logging
 | 
					import logging
 | 
				
			||||||
import hashlib
 | 
					import hashlib
 | 
				
			||||||
import tempfile
 | 
					import tempfile
 | 
				
			||||||
import random
 | 
					 | 
				
			||||||
import select
 | 
					import select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CountingBackoff(object):
 | 
					 | 
				
			||||||
    def __init__(self, maximum_retries=10):
 | 
					 | 
				
			||||||
        self.number_of_retries = 0
 | 
					 | 
				
			||||||
        self.maximum_retries = maximum_retries
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def keep_going(self):
 | 
					 | 
				
			||||||
        return self.number_of_retries < self.maximum_retries
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def succeed(self):
 | 
					 | 
				
			||||||
        self.number_of_retries = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def fail(self):
 | 
					 | 
				
			||||||
        self.number_of_retries = min(self.number_of_retries + 1,
 | 
					 | 
				
			||||||
                                     self.maximum_retries)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class RandomExponentialBackoff(CountingBackoff):
 | 
					 | 
				
			||||||
    def fail(self):
 | 
					 | 
				
			||||||
        self.number_of_retries = min(self.number_of_retries + 1,
 | 
					 | 
				
			||||||
                                     self.maximum_retries)
 | 
					 | 
				
			||||||
        # Exponential growth with ratio sqrt(2); compute random delay
 | 
					 | 
				
			||||||
        # between x and 2x where x is growing exponentially
 | 
					 | 
				
			||||||
        delay_scale = int(2 ** (self.number_of_retries / 2.0 - 1)) + 1
 | 
					 | 
				
			||||||
        delay = delay_scale + random.randint(1, delay_scale)
 | 
					 | 
				
			||||||
        message = "Sleeping for %ss [max %s] before retrying." % (delay, delay_scale * 2)
 | 
					 | 
				
			||||||
        try:
 | 
					 | 
				
			||||||
            logger.warning(message)
 | 
					 | 
				
			||||||
        except NameError:
 | 
					 | 
				
			||||||
            print message
 | 
					 | 
				
			||||||
        time.sleep(delay)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DEFAULT_SITE = "https://api.zulip.com"
 | 
					DEFAULT_SITE = "https://api.zulip.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class States:
 | 
					class States:
 | 
				
			||||||
@@ -401,7 +370,7 @@ def process_notice(notice, log):
 | 
				
			|||||||
    if is_personal:
 | 
					    if is_personal:
 | 
				
			||||||
        if body.startswith("CC:"):
 | 
					        if body.startswith("CC:"):
 | 
				
			||||||
            is_huddle = True
 | 
					            is_huddle = True
 | 
				
			||||||
            # Map "CC: sipbtest espuser" => "starnine@mit.edu,espuser@mit.edu"
 | 
					            # Map "CC: user1 user2" => "user1@mit.edu, user2@mit.edu"
 | 
				
			||||||
            huddle_recipients = [to_zulip_username(x.strip()) for x in
 | 
					            huddle_recipients = [to_zulip_username(x.strip()) for x in
 | 
				
			||||||
                                 body.split("\n")[0][4:].split()]
 | 
					                                 body.split("\n")[0][4:].split()]
 | 
				
			||||||
            if notice.sender not in huddle_recipients:
 | 
					            if notice.sender not in huddle_recipients:
 | 
				
			||||||
@@ -478,7 +447,7 @@ def quit_failed_initialization(message):
 | 
				
			|||||||
    sys.exit(1)
 | 
					    sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def zephyr_init_autoretry():
 | 
					def zephyr_init_autoretry():
 | 
				
			||||||
    backoff = RandomExponentialBackoff()
 | 
					    backoff = zulip.RandomExponentialBackoff()
 | 
				
			||||||
    while backoff.keep_going():
 | 
					    while backoff.keep_going():
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # zephyr.init() tries to clear old subscriptions, and thus
 | 
					            # zephyr.init() tries to clear old subscriptions, and thus
 | 
				
			||||||
@@ -493,7 +462,7 @@ def zephyr_init_autoretry():
 | 
				
			|||||||
    quit_failed_initialization("Could not initialize Zephyr library, quitting!")
 | 
					    quit_failed_initialization("Could not initialize Zephyr library, quitting!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def zephyr_load_session_autoretry(session_path):
 | 
					def zephyr_load_session_autoretry(session_path):
 | 
				
			||||||
    backoff = RandomExponentialBackoff()
 | 
					    backoff = zulip.RandomExponentialBackoff()
 | 
				
			||||||
    while backoff.keep_going():
 | 
					    while backoff.keep_going():
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            session = file(session_path, "r").read()
 | 
					            session = file(session_path, "r").read()
 | 
				
			||||||
@@ -508,7 +477,7 @@ def zephyr_load_session_autoretry(session_path):
 | 
				
			|||||||
    quit_failed_initialization("Could not load saved Zephyr session, quitting!")
 | 
					    quit_failed_initialization("Could not load saved Zephyr session, quitting!")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def zephyr_subscribe_autoretry(sub):
 | 
					def zephyr_subscribe_autoretry(sub):
 | 
				
			||||||
    backoff = RandomExponentialBackoff()
 | 
					    backoff = zulip.RandomExponentialBackoff()
 | 
				
			||||||
    while backoff.keep_going():
 | 
					    while backoff.keep_going():
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            zephyr.Subscriptions().add(sub)
 | 
					            zephyr.Subscriptions().add(sub)
 | 
				
			||||||
@@ -629,7 +598,9 @@ Feedback button or at support@zulip.com."""
 | 
				
			|||||||
    wrapped_content = "\n".join("\n".join(wrapper.wrap(line))
 | 
					    wrapped_content = "\n".join("\n".join(wrapper.wrap(line))
 | 
				
			||||||
            for line in message["content"].replace("@", "@@").split("\n"))
 | 
					            for line in message["content"].replace("@", "@@").split("\n"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    zwrite_args = ["zwrite", "-n", "-s", message["sender_full_name"], "-F", "Zephyr error: See http://zephyr.1ts.org/wiki/df"]
 | 
					    zwrite_args = ["zwrite", "-n", "-s", message["sender_full_name"],
 | 
				
			||||||
 | 
					                   "-F", "Zephyr error: See http://zephyr.1ts.org/wiki/df",
 | 
				
			||||||
 | 
					                   "-x", "UTF-8"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Hack to make ctl's fake username setup work :)
 | 
					    # Hack to make ctl's fake username setup work :)
 | 
				
			||||||
    if message['type'] == "stream" and zulip_account_email == "ctl@mit.edu":
 | 
					    if message['type'] == "stream" and zulip_account_email == "ctl@mit.edu":
 | 
				
			||||||
@@ -763,7 +734,7 @@ def maybe_forward_to_zephyr(message):
 | 
				
			|||||||
            logger.exception("Error forwarding message:")
 | 
					            logger.exception("Error forwarding message:")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def zulip_to_zephyr(options):
 | 
					def zulip_to_zephyr(options):
 | 
				
			||||||
    # Sync messages from zephyr to zulip
 | 
					    # Sync messages from zulip to zephyr
 | 
				
			||||||
    logger.info("Starting syncing messages.")
 | 
					    logger.info("Starting syncing messages.")
 | 
				
			||||||
    while True:
 | 
					    while True:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
[program:zmirror-USERNAME]
 | 
					[program:zmirror-USERNAME]
 | 
				
			||||||
command=python /home/zulip/zulip/bots/zephyr_mirror_backend.py --root-path=/home/zulip/zulip/bots --user=USERNAME --log-path=/home/zulip/logs/mirror-log-%(program_name)s --use-sessions --session-path=/home/zulip/zephyr_sessions/%(program_name)s --api-key-file=/home/zulip/api-keys/%(program_name)s --ignore-expired-tickets --nagios-path=/home/zulip/mirror_status/%(program_name)s --nagios-class=zulip-mirror-nagios
 | 
					command=python /home/zulip/zulip/bots/zephyr_mirror_backend.py --root-path=/home/zulip/zulip --user=USERNAME --log-path=/home/zulip/logs/mirror-log-%(program_name)s --use-sessions --session-path=/home/zulip/zephyr_sessions/%(program_name)s --api-key-file=/home/zulip/api-keys/%(program_name)s --ignore-expired-tickets --nagios-path=/home/zulip/mirror_status/%(program_name)s --nagios-class=zulip-mirror-nagios
 | 
				
			||||||
priority=200                   ; the relative start priority (default 999)
 | 
					priority=200                   ; the relative start priority (default 999)
 | 
				
			||||||
autostart=true                 ; start at supervisord start (default: true)
 | 
					autostart=true                 ; start at supervisord start (default: true)
 | 
				
			||||||
autorestart=true               ; whether/when to restart (default: unexpected)
 | 
					autorestart=true               ; whether/when to restart (default: unexpected)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,4 +39,4 @@ def format_commit_message(author, subject, commit_id):
 | 
				
			|||||||
    return '!avatar(%s) [%s](https://git.zulip.net/eng/zulip/commit/%s)\n' % (author, subject, commit_id)
 | 
					    return '!avatar(%s) [%s](https://git.zulip.net/eng/zulip/commit/%s)\n' % (author, subject, commit_id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ZULIP_API_PATH = "/home/zulip/zulip/api"
 | 
					ZULIP_API_PATH = "/home/zulip/zulip/api"
 | 
				
			||||||
ZULIP_SITE = "https://staging.zulip.com"
 | 
					ZULIP_SITE = "https://zulip.com"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,4 +11,4 @@ TRAC_BASE_TICKET_URL = "https://trac.zulip.net/ticket"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
TRAC_NOTIFY_FIELDS = ["description", "summary", "resolution", "comment", "owner"]
 | 
					TRAC_NOTIFY_FIELDS = ["description", "summary", "resolution", "comment", "owner"]
 | 
				
			||||||
ZULIP_API_PATH = "/home/zulip/zulip/api"
 | 
					ZULIP_API_PATH = "/home/zulip/zulip/api"
 | 
				
			||||||
ZULIP_SITE = "https://staging.zulip.com"
 | 
					ZULIP_SITE = "https://zulip.com"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,4 +4,4 @@
 | 
				
			|||||||
[api]
 | 
					[api]
 | 
				
			||||||
email = nagios-bot@zulip.com
 | 
					email = nagios-bot@zulip.com
 | 
				
			||||||
key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 | 
					key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 | 
				
			||||||
site = https://staging.zulip.com
 | 
					site = https://zulip.com
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,45 +1,29 @@
 | 
				
			|||||||
# -*- coding: utf-8 -*-
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
import datetime
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from south.db import db
 | 
					
 | 
				
			||||||
from south.v2 import SchemaMigration
 | 
					from django.db import models, migrations
 | 
				
			||||||
from django.db import models
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Migration(SchemaMigration):
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def forwards(self, orm):
 | 
					    dependencies = [
 | 
				
			||||||
        # Adding model 'Confirmation'
 | 
					        ('contenttypes', '0001_initial'),
 | 
				
			||||||
        db.create_table('confirmation_confirmation', (
 | 
					    ]
 | 
				
			||||||
            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
 | 
					 | 
				
			||||||
            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
 | 
					 | 
				
			||||||
            ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
 | 
					 | 
				
			||||||
            ('date_sent', self.gf('django.db.models.fields.DateTimeField')()),
 | 
					 | 
				
			||||||
            ('confirmation_key', self.gf('django.db.models.fields.CharField')(max_length=40)),
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
        db.send_create_signal('confirmation', ['Confirmation'])
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
    def backwards(self, orm):
 | 
					        migrations.CreateModel(
 | 
				
			||||||
        # Deleting model 'Confirmation'
 | 
					            name='Confirmation',
 | 
				
			||||||
        db.delete_table('confirmation_confirmation')
 | 
					            fields=[
 | 
				
			||||||
 | 
					                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
 | 
				
			||||||
 | 
					                ('object_id', models.PositiveIntegerField()),
 | 
				
			||||||
    models = {
 | 
					                ('date_sent', models.DateTimeField(verbose_name='sent')),
 | 
				
			||||||
        'confirmation.confirmation': {
 | 
					                ('confirmation_key', models.CharField(max_length=40, verbose_name='activation key')),
 | 
				
			||||||
            'Meta': {'object_name': 'Confirmation'},
 | 
					                ('content_type', models.ForeignKey(to='contenttypes.ContentType')),
 | 
				
			||||||
            'confirmation_key': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
 | 
					            ],
 | 
				
			||||||
            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
 | 
					            options={
 | 
				
			||||||
            'date_sent': ('django.db.models.fields.DateTimeField', [], {}),
 | 
					                'verbose_name': 'confirmation email',
 | 
				
			||||||
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
 | 
					                'verbose_name_plural': 'confirmation emails',
 | 
				
			||||||
            'object_id': ('django.db.models.fields.PositiveIntegerField', [], {})
 | 
					 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        'contenttypes.contenttype': {
 | 
					            bases=(models.Model,),
 | 
				
			||||||
            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
 | 
					        ),
 | 
				
			||||||
            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
 | 
					    ]
 | 
				
			||||||
            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
 | 
					 | 
				
			||||||
            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
 | 
					 | 
				
			||||||
            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    complete_apps = ['confirmation']
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,9 +34,10 @@ def generate_key():
 | 
				
			|||||||
    return generate_random_token(40)
 | 
					    return generate_random_token(40)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def generate_activation_url(key):
 | 
					def generate_activation_url(key):
 | 
				
			||||||
    current_site = Site.objects.get_current()
 | 
					    return u'%s%s%s' % (settings.EXTERNAL_URI_SCHEME,
 | 
				
			||||||
    return u'https://%s%s' % (current_site.domain,
 | 
					                        settings.EXTERNAL_HOST,
 | 
				
			||||||
            reverse('confirmation.views.confirm', kwargs={'confirmation_key': key}))
 | 
					                        reverse('confirmation.views.confirm',
 | 
				
			||||||
 | 
					                                kwargs={'confirmation_key': key}))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConfirmationManager(models.Manager):
 | 
					class ConfirmationManager(models.Manager):
 | 
				
			||||||
@@ -48,7 +49,7 @@ class ConfirmationManager(models.Manager):
 | 
				
			|||||||
            except self.model.DoesNotExist:
 | 
					            except self.model.DoesNotExist:
 | 
				
			||||||
                return False
 | 
					                return False
 | 
				
			||||||
            obj = confirmation.content_object
 | 
					            obj = confirmation.content_object
 | 
				
			||||||
            status_field = get_status_field(obj._meta.app_label, obj._meta.module_name)
 | 
					            status_field = get_status_field(obj._meta.app_label, obj._meta.model_name)
 | 
				
			||||||
            setattr(obj, status_field, getattr(settings, 'STATUS_ACTIVE', 1))
 | 
					            setattr(obj, status_field, getattr(settings, 'STATUS_ACTIVE', 1))
 | 
				
			||||||
            obj.save()
 | 
					            obj.save()
 | 
				
			||||||
            return obj
 | 
					            return obj
 | 
				
			||||||
@@ -74,7 +75,7 @@ class ConfirmationManager(models.Manager):
 | 
				
			|||||||
        if additional_context is not None:
 | 
					        if additional_context is not None:
 | 
				
			||||||
            context.update(additional_context)
 | 
					            context.update(additional_context)
 | 
				
			||||||
        templates = [
 | 
					        templates = [
 | 
				
			||||||
            'confirmation/%s_confirmation_email_subject.txt' % obj._meta.module_name,
 | 
					            'confirmation/%s_confirmation_email_subject.txt' % obj._meta.model_name,
 | 
				
			||||||
            'confirmation/confirmation_email_subject.txt',
 | 
					            'confirmation/confirmation_email_subject.txt',
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        if subject_template_path:
 | 
					        if subject_template_path:
 | 
				
			||||||
@@ -83,7 +84,7 @@ class ConfirmationManager(models.Manager):
 | 
				
			|||||||
            template = loader.select_template(templates)
 | 
					            template = loader.select_template(templates)
 | 
				
			||||||
        subject = template.render(context).strip().replace(u'\n', u' ') # no newlines, please
 | 
					        subject = template.render(context).strip().replace(u'\n', u' ') # no newlines, please
 | 
				
			||||||
        templates = [
 | 
					        templates = [
 | 
				
			||||||
            'confirmation/%s_confirmation_email_body.txt' % obj._meta.module_name,
 | 
					            'confirmation/%s_confirmation_email_body.txt' % obj._meta.model_name,
 | 
				
			||||||
            'confirmation/confirmation_email_body.txt',
 | 
					            'confirmation/confirmation_email_body.txt',
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        if body_template_path:
 | 
					        if body_template_path:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,13 +31,13 @@ def confirm(request, confirmation_key):
 | 
				
			|||||||
        'key': confirmation_key,
 | 
					        'key': confirmation_key,
 | 
				
			||||||
        'full_name': request.GET.get("full_name", None),
 | 
					        'full_name': request.GET.get("full_name", None),
 | 
				
			||||||
        'support_email': settings.ZULIP_ADMINISTRATOR,
 | 
					        'support_email': settings.ZULIP_ADMINISTRATOR,
 | 
				
			||||||
        'enterprise': settings.ENTERPRISE
 | 
					        'voyager': settings.VOYAGER
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    templates = [
 | 
					    templates = [
 | 
				
			||||||
        'confirmation/confirm.html',
 | 
					        'confirmation/confirm.html',
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
    if obj:
 | 
					    if obj:
 | 
				
			||||||
        # if we have an object, we can use specific template
 | 
					        # if we have an object, we can use specific template
 | 
				
			||||||
        templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.module_name)
 | 
					        templates.insert(0, 'confirmation/confirm_%s.html' % obj._meta.model_name)
 | 
				
			||||||
    return render_to_response(templates, ctx,
 | 
					    return render_to_response(templates, ctx,
 | 
				
			||||||
        context_instance=RequestContext(request))
 | 
					        context_instance=RequestContext(request))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,20 +2,8 @@ from django.conf.urls import patterns, url
 | 
				
			|||||||
from django.views.generic import TemplateView, RedirectView
 | 
					from django.views.generic import TemplateView, RedirectView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
urlpatterns = patterns('',
 | 
					urlpatterns = patterns('',
 | 
				
			||||||
    # Job postings
 | 
					 | 
				
			||||||
    url(r'^jobs/$', TemplateView.as_view(template_name='corporate/jobs/index.html')),
 | 
					 | 
				
			||||||
    url(r'^jobs/lead-designer/$', TemplateView.as_view(template_name='corporate/jobs/lead-designer.html')),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Zephyr/MIT
 | 
					    # Zephyr/MIT
 | 
				
			||||||
    url(r'^zephyr/$', TemplateView.as_view(template_name='corporate/zephyr.html')),
 | 
					    url(r'^zephyr/$', TemplateView.as_view(template_name='corporate/zephyr.html')),
 | 
				
			||||||
    url(r'^mit/$', TemplateView.as_view(template_name='corporate/mit.html')),
 | 
					    url(r'^mit/$', TemplateView.as_view(template_name='corporate/mit.html')),
 | 
				
			||||||
    url(r'^zephyr-mirror/$', TemplateView.as_view(template_name='corporate/zephyr-mirror.html')),
 | 
					    url(r'^zephyr-mirror/$', TemplateView.as_view(template_name='corporate/zephyr-mirror.html')),
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Marketing
 | 
					 | 
				
			||||||
    url(r'^compare/$', TemplateView.as_view(template_name='corporate/compare.html')),
 | 
					 | 
				
			||||||
    # signup form
 | 
					 | 
				
			||||||
    url(r'^signup/$', TemplateView.as_view(template_name='corporate/signup.html'),
 | 
					 | 
				
			||||||
                                         name='signup'),
 | 
					 | 
				
			||||||
    # TODO: The beta signup view should probably be moved to corporate.
 | 
					 | 
				
			||||||
    url(r'^signup/sign-me-up$', 'zerver.views.beta_signup_submission', name='beta-signup-submission'),
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					_build
 | 
				
			||||||
							
								
								
									
										192
									
								
								docs/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								docs/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,192 @@
 | 
				
			|||||||
 | 
					# Makefile for Sphinx documentation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# You can set these variables from the command line.
 | 
				
			||||||
 | 
					SPHINXOPTS    =
 | 
				
			||||||
 | 
					SPHINXBUILD   = sphinx-build
 | 
				
			||||||
 | 
					PAPER         =
 | 
				
			||||||
 | 
					BUILDDIR      = _build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# User-friendly check for sphinx-build
 | 
				
			||||||
 | 
					ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
 | 
				
			||||||
 | 
					$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Internal variables.
 | 
				
			||||||
 | 
					PAPEROPT_a4     = -D latex_paper_size=a4
 | 
				
			||||||
 | 
					PAPEROPT_letter = -D latex_paper_size=letter
 | 
				
			||||||
 | 
					ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
 | 
				
			||||||
 | 
					# the i18n builder cannot share the environment and doctrees with the others
 | 
				
			||||||
 | 
					I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					help:
 | 
				
			||||||
 | 
						@echo "Please use \`make <target>' where <target> is one of"
 | 
				
			||||||
 | 
						@echo "  html       to make standalone HTML files"
 | 
				
			||||||
 | 
						@echo "  dirhtml    to make HTML files named index.html in directories"
 | 
				
			||||||
 | 
						@echo "  singlehtml to make a single large HTML file"
 | 
				
			||||||
 | 
						@echo "  pickle     to make pickle files"
 | 
				
			||||||
 | 
						@echo "  json       to make JSON files"
 | 
				
			||||||
 | 
						@echo "  htmlhelp   to make HTML files and a HTML help project"
 | 
				
			||||||
 | 
						@echo "  qthelp     to make HTML files and a qthelp project"
 | 
				
			||||||
 | 
						@echo "  applehelp  to make an Apple Help Book"
 | 
				
			||||||
 | 
						@echo "  devhelp    to make HTML files and a Devhelp project"
 | 
				
			||||||
 | 
						@echo "  epub       to make an epub"
 | 
				
			||||||
 | 
						@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
 | 
				
			||||||
 | 
						@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
 | 
				
			||||||
 | 
						@echo "  latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
 | 
				
			||||||
 | 
						@echo "  text       to make text files"
 | 
				
			||||||
 | 
						@echo "  man        to make manual pages"
 | 
				
			||||||
 | 
						@echo "  texinfo    to make Texinfo files"
 | 
				
			||||||
 | 
						@echo "  info       to make Texinfo files and run them through makeinfo"
 | 
				
			||||||
 | 
						@echo "  gettext    to make PO message catalogs"
 | 
				
			||||||
 | 
						@echo "  changes    to make an overview of all changed/added/deprecated items"
 | 
				
			||||||
 | 
						@echo "  xml        to make Docutils-native XML files"
 | 
				
			||||||
 | 
						@echo "  pseudoxml  to make pseudoxml-XML files for display purposes"
 | 
				
			||||||
 | 
						@echo "  linkcheck  to check all external links for integrity"
 | 
				
			||||||
 | 
						@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
 | 
				
			||||||
 | 
						@echo "  coverage   to run coverage check of the documentation (if enabled)"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						rm -rf $(BUILDDIR)/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dirhtml:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					singlehtml:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pickle:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished; now you can process the pickle files."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					json:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished; now you can process the JSON files."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					htmlhelp:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished; now you can run HTML Help Workshop with the" \
 | 
				
			||||||
 | 
						      ".hhp project file in $(BUILDDIR)/htmlhelp."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qthelp:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished; now you can run "qcollectiongenerator" with the" \
 | 
				
			||||||
 | 
						      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
 | 
				
			||||||
 | 
						@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/zulip-contributor-docs.qhcp"
 | 
				
			||||||
 | 
						@echo "To view the help file:"
 | 
				
			||||||
 | 
						@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zulip-contributor-docs.qhc"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					applehelp:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
 | 
				
			||||||
 | 
						@echo "N.B. You won't be able to view it unless you put it in" \
 | 
				
			||||||
 | 
						      "~/Library/Documentation/Help or install it in your application" \
 | 
				
			||||||
 | 
						      "bundle."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					devhelp:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished."
 | 
				
			||||||
 | 
						@echo "To view the help file:"
 | 
				
			||||||
 | 
						@echo "# mkdir -p $$HOME/.local/share/devhelp/zulip-contributor-docs"
 | 
				
			||||||
 | 
						@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zulip-contributor-docs"
 | 
				
			||||||
 | 
						@echo "# devhelp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					epub:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latex:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
 | 
				
			||||||
 | 
						@echo "Run \`make' in that directory to run these through (pdf)latex" \
 | 
				
			||||||
 | 
						      "(use \`make latexpdf' here to do that automatically)."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latexpdf:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 | 
				
			||||||
 | 
						@echo "Running LaTeX files through pdflatex..."
 | 
				
			||||||
 | 
						$(MAKE) -C $(BUILDDIR)/latex all-pdf
 | 
				
			||||||
 | 
						@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latexpdfja:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 | 
				
			||||||
 | 
						@echo "Running LaTeX files through platex and dvipdfmx..."
 | 
				
			||||||
 | 
						$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
 | 
				
			||||||
 | 
						@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					text:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The text files are in $(BUILDDIR)/text."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					man:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					texinfo:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
 | 
				
			||||||
 | 
						@echo "Run \`make' in that directory to run these through makeinfo" \
 | 
				
			||||||
 | 
						      "(use \`make info' here to do that automatically)."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					info:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
 | 
				
			||||||
 | 
						@echo "Running Texinfo files through makeinfo..."
 | 
				
			||||||
 | 
						make -C $(BUILDDIR)/texinfo info
 | 
				
			||||||
 | 
						@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					gettext:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					changes:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "The overview file is in $(BUILDDIR)/changes."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					linkcheck:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Link check complete; look for any errors in the above output " \
 | 
				
			||||||
 | 
						      "or in $(BUILDDIR)/linkcheck/output.txt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					doctest:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
 | 
				
			||||||
 | 
						@echo "Testing of doctests in the sources finished, look at the " \
 | 
				
			||||||
 | 
						      "results in $(BUILDDIR)/doctest/output.txt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					coverage:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
 | 
				
			||||||
 | 
						@echo "Testing of coverage in the sources finished, look at the " \
 | 
				
			||||||
 | 
						      "results in $(BUILDDIR)/coverage/python.txt."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					xml:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pseudoxml:
 | 
				
			||||||
 | 
						$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
 | 
				
			||||||
 | 
						@echo
 | 
				
			||||||
 | 
						@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
 | 
				
			||||||
							
								
								
									
										23
									
								
								docs/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					These docs are written in rST, and are included on the zulip.org website
 | 
				
			||||||
 | 
					as well as on each development installation.  Many of these docs
 | 
				
			||||||
 | 
					have been ported from the internal docs of Zulip Inc.,
 | 
				
			||||||
 | 
					and may need to be updated for use in the open source project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To generate HTML docs locally from rST:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * `pip install sphinx`
 | 
				
			||||||
 | 
					   * In this directory, `make html`. Output appears in a `_build/html` subdirectory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To create rST from MediaWiki input:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * Use `pandoc -r mediawiki -w rst` on MediaWiki source.
 | 
				
			||||||
 | 
					   * Use unescape.py to remove any leftover HTML entities (often inside <pre>
 | 
				
			||||||
 | 
					     tags and the like).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We can use pandoc to translate mediawiki into reStructuredText, but some things need fixing up:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * Add page titles.
 | 
				
			||||||
 | 
					   * Review pages for formatting (especially inline code chunks) and content.
 | 
				
			||||||
 | 
					   * Fix wiki links?
 | 
				
			||||||
 | 
					   * Add pages to the table of contents (`index.rst`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										10
									
								
								docs/_static/theme_overrides.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								docs/_static/theme_overrides.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/* override table width restrictions */
 | 
				
			||||||
 | 
					.wy-table-responsive table td, .wy-table-responsive table th {
 | 
				
			||||||
 | 
					    /* !important prevents the common CSS stylesheets from
 | 
				
			||||||
 | 
					       overriding this as on RTD they are loaded after this stylesheet */
 | 
				
			||||||
 | 
					    white-space: normal !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.wy-table-responsive {
 | 
				
			||||||
 | 
					    overflow: visible !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										484
									
								
								docs/code-style.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										484
									
								
								docs/code-style.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,484 @@
 | 
				
			|||||||
 | 
					==========================
 | 
				
			||||||
 | 
					Code style and conventions
 | 
				
			||||||
 | 
					==========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Be consistent!
 | 
				
			||||||
 | 
					==============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Look at the surrounding code, or a similar part of the project, and
 | 
				
			||||||
 | 
					try to do the same thing. If you think the other code has actively bad
 | 
				
			||||||
 | 
					style, fix it (in a separate commit).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When in doubt, send an email to zulip-devel@googlegroups.com with your
 | 
				
			||||||
 | 
					question.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Lint tools
 | 
				
			||||||
 | 
					==========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can run them all at once with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ./tools/lint-all
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can set this up as a local Git commit hook with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ``tools/setup-git-repo``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The Vagrant setup process runs this for you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``lint-all`` runs many lint checks in parallel, including
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Javascript (`JSLint <http://www.jslint.com/>`__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ``tools/jslint/check-all.js`` contains a pretty fine-grained set of
 | 
				
			||||||
 | 
					    JSLint options, rule exceptions, and allowed global variables. If you
 | 
				
			||||||
 | 
					    add a new global, you'll need to add it to the list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Python (`Pyflakes <http://pypi.python.org/pypi/pyflakes>`__)
 | 
				
			||||||
 | 
					- templates
 | 
				
			||||||
 | 
					- Puppet configuration
 | 
				
			||||||
 | 
					- custom checks (e.g. trailing whitespace and spaces-not-tabs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Secrets
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Please don't put any passwords, secret access keys, etc. inline in the
 | 
				
			||||||
 | 
					code.  Instead, use the ``get_secret`` function in
 | 
				
			||||||
 | 
					``zproject/settings.py`` to read secrets from ``/etc/zulip/secrets.conf``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dangerous constructs
 | 
				
			||||||
 | 
					====================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Misuse of database queries
 | 
				
			||||||
 | 
					--------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Look out for Django code like this::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   [Foo.objects.get(id=bar.x.id)
 | 
				
			||||||
 | 
					   for bar in Bar.objects.filter(...)
 | 
				
			||||||
 | 
					   if  bar.baz < 7]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This will make one database query for each ``Bar``, which is slow in
 | 
				
			||||||
 | 
					production (but not in local testing!). Instead of a list comprehension,
 | 
				
			||||||
 | 
					write a single query using Django's `QuerySet
 | 
				
			||||||
 | 
					API <https://docs.djangoproject.com/en/dev/ref/models/querysets/>`__.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you can't rewrite it as a single query, that's a sign that something
 | 
				
			||||||
 | 
					is wrong with the database schema. So don't defer this optimization when
 | 
				
			||||||
 | 
					performing schema changes, or else you may later find that it's
 | 
				
			||||||
 | 
					impossible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					UserProfile.objects.get() / Client.objects.get / etc.
 | 
				
			||||||
 | 
					-----------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In our Django code, never do direct
 | 
				
			||||||
 | 
					``UserProfile.objects.get(email=foo)`` database queries. Instead always
 | 
				
			||||||
 | 
					use ``get_user_profile_by_{email,id}``. There are 3 reasons for this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#. It's guaranteed to correctly do a case-inexact lookup
 | 
				
			||||||
 | 
					#. It fetches the user object from memcached, which is faster
 | 
				
			||||||
 | 
					#. It always fetches a UserProfile object which has been queried using
 | 
				
			||||||
 | 
					   .selected\_related(), and thus will perform well when one later
 | 
				
			||||||
 | 
					   accesses related models like the Realm.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Similarly we have ``get_client`` and ``get_stream`` functions to fetch
 | 
				
			||||||
 | 
					those commonly accessed objects via memcached.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using Django model objects as keys in sets/dicts
 | 
				
			||||||
 | 
					------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use Django model objects as keys in sets/dictionaries -- you will
 | 
				
			||||||
 | 
					get unexpected behavior when dealing with objects obtained from
 | 
				
			||||||
 | 
					different database queries:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example,
 | 
				
			||||||
 | 
					``UserProfile.objects.only("id").get(id=17) in set([UserProfile.objects.get(id=17)])``
 | 
				
			||||||
 | 
					is False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should work with the IDs instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					user\_profile.save()
 | 
				
			||||||
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should always pass the update\_fields keyword argument to .save()
 | 
				
			||||||
 | 
					when modifying an existing Django model object. By default, .save() will
 | 
				
			||||||
 | 
					overwrite every value in the column, which results in lots of race
 | 
				
			||||||
 | 
					conditions where unrelated changes made by one thread can be
 | 
				
			||||||
 | 
					accidentally overwritten by another thread that fetched its UserProfile
 | 
				
			||||||
 | 
					object before the first thread wrote out its change.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using raw saves to update important model objects
 | 
				
			||||||
 | 
					-------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In most cases, we already have a function in zephyr/lib/actions.py with
 | 
				
			||||||
 | 
					a name like do\_activate\_user that will correctly handle lookups,
 | 
				
			||||||
 | 
					caching, and notifying running browsers via the event system about your
 | 
				
			||||||
 | 
					change. So please check whether such a function exists before writing
 | 
				
			||||||
 | 
					new code to modify a model object, since your new code has a good chance
 | 
				
			||||||
 | 
					of getting at least one of these things wrong.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``x.attr('zid')`` vs. ``rows.id(x)``
 | 
				
			||||||
 | 
					------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Our message row DOM elements have a custom attribute ``zid`` which
 | 
				
			||||||
 | 
					contains the numerical message ID. **Don't access this directly as**
 | 
				
			||||||
 | 
					``x.attr('zid')`` ! The result will be a string and comparisons (e.g.
 | 
				
			||||||
 | 
					with ``<=``) will give the wrong result, occasionally, just enough to
 | 
				
			||||||
 | 
					make a bug that's impossible to track down.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should instead use the ``id`` function from the ``rows`` module, as
 | 
				
			||||||
 | 
					in ``rows.id(x)``. This returns a number. Even in cases where you do
 | 
				
			||||||
 | 
					want a string, use the ``id`` function, as it will simplify future code
 | 
				
			||||||
 | 
					changes. In most contexts in JavaScript where a string is needed, you
 | 
				
			||||||
 | 
					can pass a number without any explicit conversion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Javascript var
 | 
				
			||||||
 | 
					--------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Always declare Javascript variables using ``var``::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   var x = ...;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In a function, ``var`` is necessary or else ``x`` will be a global
 | 
				
			||||||
 | 
					variable. For variables declared at global scope, this has no effect,
 | 
				
			||||||
 | 
					but we do it for consistency.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Javascript has function scope only, not block scope. This means that a
 | 
				
			||||||
 | 
					``var`` declaration inside a ``for`` or ``if`` acts the same as a
 | 
				
			||||||
 | 
					``var`` declaration at the beginning of the surrounding ``function``. To
 | 
				
			||||||
 | 
					avoid confusion, declare all variables at the top of a function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Javascript ``for (i in myArray)``
 | 
				
			||||||
 | 
					---------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use it:
 | 
				
			||||||
 | 
					`[1] <http://stackoverflow.com/questions/500504/javascript-for-in-with-arrays>`__,
 | 
				
			||||||
 | 
					`[2] <http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#for-in_loop>`__,
 | 
				
			||||||
 | 
					`[3] <http://www.jslint.com/lint.html#forin>`__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jQuery global state
 | 
				
			||||||
 | 
					-------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't mess with jQuery global state once the app has loaded. Code like
 | 
				
			||||||
 | 
					this is very dangerous::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $.ajaxSetup({ async: false });
 | 
				
			||||||
 | 
					   $.get(...);
 | 
				
			||||||
 | 
					   $.ajaxSetup({ async: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jQuery and the browser are free to run other code while the request is
 | 
				
			||||||
 | 
					pending, which could perform other Ajax requests with the altered
 | 
				
			||||||
 | 
					settings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Instead, switch to the more general |ajax|_ function, which can take options
 | 
				
			||||||
 | 
					like ``async``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. |ajax| replace:: ``$.ajax``
 | 
				
			||||||
 | 
					.. _ajax: http://api.jquery.com/jQuery.ajax
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					State and logs files
 | 
				
			||||||
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Do not write state and logs files inside the current working directory
 | 
				
			||||||
 | 
					in the production environment. This will not how you expect, because the
 | 
				
			||||||
 | 
					current working directory for the app changes every time we do a deploy.
 | 
				
			||||||
 | 
					Instead, hardcode a path in settings.py -- see SERVER\_LOG\_PATH in
 | 
				
			||||||
 | 
					settings.py for an example.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					JS array/object manipulation
 | 
				
			||||||
 | 
					============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For generic functions that operate on arrays or JavaScript objects, you
 | 
				
			||||||
 | 
					should generally use `Underscore <http://underscorejs.org/>`__. We used
 | 
				
			||||||
 | 
					to use jQuery's utility functions, but the Underscore equivalents are
 | 
				
			||||||
 | 
					more consistent, better-behaved and offer more choices.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A quick conversion table::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $.each → _.each (parameters to the callback reversed)
 | 
				
			||||||
 | 
					      $.inArray → _.indexOf (parameters reversed)
 | 
				
			||||||
 | 
					      $.grep → _.filter
 | 
				
			||||||
 | 
					      $.map → _.map
 | 
				
			||||||
 | 
					      $.extend → _.extend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There's a subtle difference in the case of ``_.extend``; it will replace
 | 
				
			||||||
 | 
					attributes with undefined, whereas jQuery won't::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      $.extend({foo: 2}, {foo: undefined});  // yields {foo: 2}, BUT...
 | 
				
			||||||
 | 
					      _.extend({foo: 2}, {foo: undefined});  // yields {foo: undefined}!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Also, ``_.each`` does not let you break out of the iteration early by
 | 
				
			||||||
 | 
					returning false, the way jQuery's version does. If you're doing this,
 | 
				
			||||||
 | 
					you probably want ``_.find``, ``_.every``, or ``_.any``, rather than
 | 
				
			||||||
 | 
					'each'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Some Underscore functions have multiple names. You should always use the
 | 
				
			||||||
 | 
					canonical name (given in large print in the Underscore documentation),
 | 
				
			||||||
 | 
					with the exception of ``_.any``, which we prefer over the less clear
 | 
				
			||||||
 | 
					'some'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More arbitrary style things
 | 
				
			||||||
 | 
					===========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					General
 | 
				
			||||||
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Indentation is four space characters for Python, JS, CSS, and shell
 | 
				
			||||||
 | 
					scripts. Indentation is two space characters for HTML templates.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We never use tabs anywhere in source code we write, but we have some
 | 
				
			||||||
 | 
					third-party files which contain tabs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Keep third-party static files under the directory
 | 
				
			||||||
 | 
					``zephyr/static/third/``, with one subdirectory per third-party project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We don't have an absolute hard limit on line length, but we should avoid
 | 
				
			||||||
 | 
					extremely long lines. A general guideline is: refactor stuff to get it
 | 
				
			||||||
 | 
					under 85 characters, unless that makes the code a lot uglier, in which
 | 
				
			||||||
 | 
					case it's fine to go up to 120 or so.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Whitespace guidelines:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Put one space (or more for alignment) around binary arithmetic and
 | 
				
			||||||
 | 
					   equality operators.
 | 
				
			||||||
 | 
					-  Put one space around each part of the ternary operator.
 | 
				
			||||||
 | 
					-  Put one space between keywords like ``if`` and ``while`` and their
 | 
				
			||||||
 | 
					   associated open paren.
 | 
				
			||||||
 | 
					-  Put one space between the closing paren for ``if`` and ``while``-like
 | 
				
			||||||
 | 
					   constructs and the opening curly brace. Put the curly brace on the
 | 
				
			||||||
 | 
					   same line unless doing otherwise improves readability.
 | 
				
			||||||
 | 
					-  Put no space before or after the open paren for function calls and no
 | 
				
			||||||
 | 
					   space before the close paren for function calls.
 | 
				
			||||||
 | 
					-  For the comma operator and colon operator in languages where it is
 | 
				
			||||||
 | 
					   used for inline dictionaries, put no space before it and at least one
 | 
				
			||||||
 | 
					   space after. Only use more than one space for alignment.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Javascript
 | 
				
			||||||
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use ``==`` and ``!=`` because these operators perform type
 | 
				
			||||||
 | 
					coercions, which can mask bugs. Always use ``===`` and ``!==``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					End every statement with a semicolon.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``if`` statements with no braces are allowed, if the body is simple and
 | 
				
			||||||
 | 
					its extent is abundantly clear from context and formatting.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Anonymous functions should have spaces before and after the argument
 | 
				
			||||||
 | 
					list::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   var x = function (foo, bar) { // ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When calling a function with an anonymous function as an argument, use
 | 
				
			||||||
 | 
					this style::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $.get('foo', function (data) {
 | 
				
			||||||
 | 
					       var x = ...;
 | 
				
			||||||
 | 
					       // ...
 | 
				
			||||||
 | 
					   });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The inner function body is indented one level from the outer function
 | 
				
			||||||
 | 
					call. The closing brace for the inner function and the closing
 | 
				
			||||||
 | 
					parenthesis for the outer call are together on the same line. This style
 | 
				
			||||||
 | 
					isn't necessarily appropriate for calls with multiple anonymous
 | 
				
			||||||
 | 
					functions or other arguments following them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $(function () { ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rather than
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   $(document).ready(function () { ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and combine adjacent on-ready functions, if they are logically related.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The best way to build complicated DOM elements is a Mustache template
 | 
				
			||||||
 | 
					like ``zephyr/static/templates/message.handlebars``. For simpler things
 | 
				
			||||||
 | 
					you can use jQuery DOM building APIs like so::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   var new_tr = $('<tr />').attr('id', zephyr.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Passing a HTML string to jQuery is fine for simple hardcoded things::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   foo.append('<p id="selected">foo</p>');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					but avoid programmatically building complicated strings.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We used to favor attaching behaviors in templates like so::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <p onclick="select_zephyr({{id}})">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					but there are some reasons to prefer attaching events using jQuery code:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Potential huge performance gains by using delegated events where
 | 
				
			||||||
 | 
					   possible
 | 
				
			||||||
 | 
					-  When calling a function from an ``onclick`` attribute, ``this`` is
 | 
				
			||||||
 | 
					   not bound to the element like you might think
 | 
				
			||||||
 | 
					-  jQuery does event normalization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Either way, avoid complicated JavaScript code inside HTML attributes;
 | 
				
			||||||
 | 
					call a helper function instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					HTML / CSS
 | 
				
			||||||
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use the ``style=`` attribute. Instead, define logical classes and
 | 
				
			||||||
 | 
					put your styles in ``zulip.css``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use the tag name in a selector unless you have to. In other words,
 | 
				
			||||||
 | 
					use ``.foo`` instead of ``span.foo``. We shouldn't have to care if the
 | 
				
			||||||
 | 
					tag type changes in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Don't use inline event handlers (``onclick=``, etc. attributes).
 | 
				
			||||||
 | 
					Instead, attach a jQuery event handler
 | 
				
			||||||
 | 
					(``$('#foo').on('click', function () {...})``) when the DOM is ready
 | 
				
			||||||
 | 
					(inside a ``$(function () {...})`` block).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use this format when you have the same block applying to multiple CSS
 | 
				
			||||||
 | 
					styles (separate lines for each selector)::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    selector1,
 | 
				
			||||||
 | 
					    selector2 {
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Python
 | 
				
			||||||
 | 
					------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Scripts should start with ``#!/usr/bin/env python`` and not
 | 
				
			||||||
 | 
					   ``#!/usr/bin/python``. See commit ``437d4aee`` for an explanation of
 | 
				
			||||||
 | 
					   why. Don't put such a line on a Python file unless it's meaningful to
 | 
				
			||||||
 | 
					   run it as a script. (Some libraries can also be run as scripts, e.g.
 | 
				
			||||||
 | 
					   to run a test suite.)
 | 
				
			||||||
 | 
					-  The first import in a file should be
 | 
				
			||||||
 | 
					   ``from __future__ import absolute_import``, per `PEP
 | 
				
			||||||
 | 
					   328 <http://docs.python.org/2/whatsnew/2.5.html#pep-328-absolute-and-relative-imports>`__
 | 
				
			||||||
 | 
					-  Put all imports together at the top of the file, absent a compelling
 | 
				
			||||||
 | 
					   reason to do otherwise.
 | 
				
			||||||
 | 
					-  Unpacking sequences doesn't require list brackets::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      [x, y] = xs    # unnecessary
 | 
				
			||||||
 | 
					      x, y = xs      # better
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  For string formatting, use ``x % (y,)`` rather than ``x % y``, to
 | 
				
			||||||
 | 
					   avoid ambiguity if ``y`` happens to be a tuple.
 | 
				
			||||||
 | 
					-  When selecting by id, don't use ``foo.pk`` when you mean ``foo.id``.
 | 
				
			||||||
 | 
					   E.g.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      recipient = Recipient(type_id=huddle.pk, type=Recipient.HUDDLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   should be written as
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      recipient = Recipient(type_id=huddle.id, type=Recipient.HUDDLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   in case we ever change the primary keys.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Version Control
 | 
				
			||||||
 | 
					===============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Commit Discipline
 | 
				
			||||||
 | 
					-----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We follow the Git project's own commit discipline practice of "Each
 | 
				
			||||||
 | 
					commit is a minimal coherent idea".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Coherency requirements for any commit:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  It should pass tests (so test updates needed by a change should be in
 | 
				
			||||||
 | 
					   the same commit as the original change, not a separate "fix the tests
 | 
				
			||||||
 | 
					   that were broken by the last commit" commit).
 | 
				
			||||||
 | 
					-  It should be safe to deploy individually, or comment in detail in the
 | 
				
			||||||
 | 
					   commit message as to why it isn't (maybe with a [manual] tag). So
 | 
				
			||||||
 | 
					   implementing a new API endpoint in one commit and then adding the
 | 
				
			||||||
 | 
					   security checks in a future commit should be avoided -- the security
 | 
				
			||||||
 | 
					   checks should be there from the beginning.
 | 
				
			||||||
 | 
					-  Error handling should generally be included along with the code that
 | 
				
			||||||
 | 
					   might trigger the error.
 | 
				
			||||||
 | 
					-  TODO comments should be in the commit that introduces the
 | 
				
			||||||
 | 
					   issue or functionality with further work required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When you should be minimal:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Significant refactorings should be done in a separate commit from
 | 
				
			||||||
 | 
					   functional changes.
 | 
				
			||||||
 | 
					-  Moving code from one file to another should be done in a separate
 | 
				
			||||||
 | 
					   commits from functional changes or even refactoring within a file.
 | 
				
			||||||
 | 
					-  2 different refactorings should be done in different commits.
 | 
				
			||||||
 | 
					-  2 different features should be done in different commits.
 | 
				
			||||||
 | 
					-  If you find yourself writing a commit message that reads like a list
 | 
				
			||||||
 | 
					   of somewhat dissimilar things that you did, you probably should have
 | 
				
			||||||
 | 
					   just done 2 commits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When not to be overly minimal:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  For completely new features, you don't necessarily need to split out
 | 
				
			||||||
 | 
					   new commits for each little subfeature of the new feature. E.g. if
 | 
				
			||||||
 | 
					   you're writing a new tool from scratch, it's fine to have the initial
 | 
				
			||||||
 | 
					   tool have plenty of options/features without doing separate commits
 | 
				
			||||||
 | 
					   for each one.  That said, reviewing a 2000-line giant blob of new
 | 
				
			||||||
 | 
					   code isn't fun, so please be thoughtful about submitting things in
 | 
				
			||||||
 | 
					   reviewable units.
 | 
				
			||||||
 | 
					-  Don't bother to split back end commits from front end commits, even
 | 
				
			||||||
 | 
					   though the backend can often be coherent on its own.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Other considerations:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Overly fine commits are easily squashed, but not vice versa, so err
 | 
				
			||||||
 | 
					   toward small commits, and the code reviewer can advise on squashing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It can take some practice to get used to writing your commits this
 | 
				
			||||||
 | 
					way.  For example, often you'll start adding a feature, and discover
 | 
				
			||||||
 | 
					you need to a refactoring partway through writing the feature.  When
 | 
				
			||||||
 | 
					that happens, we recommend stashing your partial feature, do the
 | 
				
			||||||
 | 
					refactoring, commit it, and then finish implementing your feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Commit Messages
 | 
				
			||||||
 | 
					---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  The first line of commit messages should be written in the imperative
 | 
				
			||||||
 | 
					   and be kept relatively short while concisely explaining what the
 | 
				
			||||||
 | 
					   commit does. For example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bad::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   bugfix
 | 
				
			||||||
 | 
					   gather_subscriptions was broken
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Good::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Prevent gather_subscriptions from throwing an exception when given bad input.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Please use a complete sentence, ending with a period.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  The rest of the commit message should be written in full prose and
 | 
				
			||||||
 | 
					   explain why and how the change was made. If the commit makes
 | 
				
			||||||
 | 
					   performance improvements, you should generally include some rough
 | 
				
			||||||
 | 
					   benchmarks showing that it actually improves the performance.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  In your commit message, you should describe any manual testing you
 | 
				
			||||||
 | 
					   did in addition to running the automated tests, and any aspects of
 | 
				
			||||||
 | 
					   the commit that you think are questionable and you'd like special
 | 
				
			||||||
 | 
					   attention applied to.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tests
 | 
				
			||||||
 | 
					-----
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					All significant new features should come with tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Third party code
 | 
				
			||||||
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When adding new third-party packages to our codebase, please include
 | 
				
			||||||
 | 
					"[third]" at the beginning of the commit message. You don't necessarily
 | 
				
			||||||
 | 
					need to do this when patching third-party code that's already in tree.
 | 
				
			||||||
							
								
								
									
										295
									
								
								docs/conf.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								docs/conf.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,295 @@
 | 
				
			|||||||
 | 
					# -*- coding: utf-8 -*-
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# zulip-contributor-docs documentation build configuration file, created by
 | 
				
			||||||
 | 
					# sphinx-quickstart on Mon Aug 17 16:24:04 2015.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This file is execfile()d with the current directory set to its
 | 
				
			||||||
 | 
					# containing dir.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Note that not all possible configuration values are present in this
 | 
				
			||||||
 | 
					# autogenerated file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# All configuration values have a default; values that are commented out
 | 
				
			||||||
 | 
					# serve to show the default.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import shlex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If extensions (or modules to document with autodoc) are in another directory,
 | 
				
			||||||
 | 
					# add these directories to sys.path here. If the directory is relative to the
 | 
				
			||||||
 | 
					# documentation root, use os.path.abspath to make it absolute, like shown here.
 | 
				
			||||||
 | 
					#sys.path.insert(0, os.path.abspath('.'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -- General configuration ------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If your documentation needs a minimal Sphinx version, state it here.
 | 
				
			||||||
 | 
					#needs_sphinx = '1.0'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add any Sphinx extension module names here, as strings. They can be
 | 
				
			||||||
 | 
					# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 | 
				
			||||||
 | 
					# ones.
 | 
				
			||||||
 | 
					extensions = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add any paths that contain templates here, relative to this directory.
 | 
				
			||||||
 | 
					templates_path = ['_templates']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The suffix(es) of source filenames.
 | 
				
			||||||
 | 
					# You can specify multiple suffix as a list of string:
 | 
				
			||||||
 | 
					# source_suffix = ['.rst', '.md']
 | 
				
			||||||
 | 
					source_suffix = '.rst'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The encoding of source files.
 | 
				
			||||||
 | 
					#source_encoding = 'utf-8-sig'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The master toctree document.
 | 
				
			||||||
 | 
					master_doc = 'index'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# General information about the project.
 | 
				
			||||||
 | 
					project = u'Zulip'
 | 
				
			||||||
 | 
					copyright = u'2015, The Zulip Team'
 | 
				
			||||||
 | 
					author = u'The Zulip Team'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The version info for the project you're documenting, acts as replacement for
 | 
				
			||||||
 | 
					# |version| and |release|, also used in various other places throughout the
 | 
				
			||||||
 | 
					# built documents.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The short X.Y version.
 | 
				
			||||||
 | 
					version = '0.1'
 | 
				
			||||||
 | 
					# The full version, including alpha/beta/rc tags.
 | 
				
			||||||
 | 
					release = '0.1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The language for content autogenerated by Sphinx. Refer to documentation
 | 
				
			||||||
 | 
					# for a list of supported languages.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This is also used if you do content translation via gettext catalogs.
 | 
				
			||||||
 | 
					# Usually you set "language" from the command line for these cases.
 | 
				
			||||||
 | 
					language = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# There are two options for replacing |today|: either, you set today to some
 | 
				
			||||||
 | 
					# non-false value, then it is used:
 | 
				
			||||||
 | 
					#today = ''
 | 
				
			||||||
 | 
					# Else, today_fmt is used as the format for a strftime call.
 | 
				
			||||||
 | 
					#today_fmt = '%B %d, %Y'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# List of patterns, relative to source directory, that match files and
 | 
				
			||||||
 | 
					# directories to ignore when looking for source files.
 | 
				
			||||||
 | 
					exclude_patterns = ['_build']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The reST default role (used for this markup: `text`) to use for all
 | 
				
			||||||
 | 
					# documents.
 | 
				
			||||||
 | 
					#default_role = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, '()' will be appended to :func: etc. cross-reference text.
 | 
				
			||||||
 | 
					#add_function_parentheses = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, the current module name will be prepended to all description
 | 
				
			||||||
 | 
					# unit titles (such as .. function::).
 | 
				
			||||||
 | 
					#add_module_names = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, sectionauthor and moduleauthor directives will be shown in the
 | 
				
			||||||
 | 
					# output. They are ignored by default.
 | 
				
			||||||
 | 
					#show_authors = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of the Pygments (syntax highlighting) style to use.
 | 
				
			||||||
 | 
					pygments_style = 'sphinx'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A list of ignored prefixes for module index sorting.
 | 
				
			||||||
 | 
					#modindex_common_prefix = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, keep warnings as "system message" paragraphs in the built documents.
 | 
				
			||||||
 | 
					#keep_warnings = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, `todo` and `todoList` produce output, else they produce nothing.
 | 
				
			||||||
 | 
					todo_include_todos = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -- Options for HTML output ----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The theme to use for HTML and HTML Help pages.  See the documentation for
 | 
				
			||||||
 | 
					# a list of builtin themes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Read The Docs can't import sphinx_rtd_theme, so don't import it there.
 | 
				
			||||||
 | 
					on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if not on_rtd:
 | 
				
			||||||
 | 
					    import sphinx_rtd_theme
 | 
				
			||||||
 | 
					    html_theme = 'sphinx_rtd_theme'
 | 
				
			||||||
 | 
					    html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Theme options are theme-specific and customize the look and feel of a theme
 | 
				
			||||||
 | 
					# further.  For a list of options available for each theme, see the
 | 
				
			||||||
 | 
					# documentation.
 | 
				
			||||||
 | 
					#html_theme_options = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add any paths that contain custom themes here, relative to this directory.
 | 
				
			||||||
 | 
					#html_theme_path = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name for this set of Sphinx documents.  If None, it defaults to
 | 
				
			||||||
 | 
					# "<project> v<release> documentation".
 | 
				
			||||||
 | 
					#html_title = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A shorter title for the navigation bar.  Default is the same as html_title.
 | 
				
			||||||
 | 
					#html_short_title = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of an image file (relative to this directory) to place at the top
 | 
				
			||||||
 | 
					# of the sidebar.
 | 
				
			||||||
 | 
					#html_logo = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of an image file (within the static path) to use as favicon of the
 | 
				
			||||||
 | 
					# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
 | 
				
			||||||
 | 
					# pixels large.
 | 
				
			||||||
 | 
					#html_favicon = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add any paths that contain custom static files (such as style sheets) here,
 | 
				
			||||||
 | 
					# relative to this directory. They are copied after the builtin static files,
 | 
				
			||||||
 | 
					# so a file named "default.css" will overwrite the builtin "default.css".
 | 
				
			||||||
 | 
					html_static_path = ['_static']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Add any extra paths that contain custom files (such as robots.txt or
 | 
				
			||||||
 | 
					# .htaccess) here, relative to this directory. These files are copied
 | 
				
			||||||
 | 
					# directly to the root of the documentation.
 | 
				
			||||||
 | 
					#html_extra_path = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
 | 
				
			||||||
 | 
					# using the given strftime format.
 | 
				
			||||||
 | 
					#html_last_updated_fmt = '%b %d, %Y'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, SmartyPants will be used to convert quotes and dashes to
 | 
				
			||||||
 | 
					# typographically correct entities.
 | 
				
			||||||
 | 
					#html_use_smartypants = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Custom sidebar templates, maps document names to template names.
 | 
				
			||||||
 | 
					#html_sidebars = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional templates that should be rendered to pages, maps page names to
 | 
				
			||||||
 | 
					# template names.
 | 
				
			||||||
 | 
					#html_additional_pages = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If false, no module index is generated.
 | 
				
			||||||
 | 
					#html_domain_indices = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If false, no index is generated.
 | 
				
			||||||
 | 
					#html_use_index = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, the index is split into individual pages for each letter.
 | 
				
			||||||
 | 
					#html_split_index = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, links to the reST sources are added to the pages.
 | 
				
			||||||
 | 
					#html_show_sourcelink = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
 | 
				
			||||||
 | 
					#html_show_sphinx = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
 | 
				
			||||||
 | 
					#html_show_copyright = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, an OpenSearch description file will be output, and all pages will
 | 
				
			||||||
 | 
					# contain a <link> tag referring to it.  The value of this option must be the
 | 
				
			||||||
 | 
					# base URL from which the finished HTML is served.
 | 
				
			||||||
 | 
					#html_use_opensearch = ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This is the file name suffix for HTML files (e.g. ".xhtml").
 | 
				
			||||||
 | 
					#html_file_suffix = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Language to be used for generating the HTML full-text search index.
 | 
				
			||||||
 | 
					# Sphinx supports the following languages:
 | 
				
			||||||
 | 
					#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
 | 
				
			||||||
 | 
					#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
 | 
				
			||||||
 | 
					#html_search_language = 'en'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# A dictionary with options for the search language support, empty by default.
 | 
				
			||||||
 | 
					# Now only 'ja' uses this config value
 | 
				
			||||||
 | 
					#html_search_options = {'type': 'default'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of a javascript file (relative to the configuration directory) that
 | 
				
			||||||
 | 
					# implements a search results scorer. If empty, the default will be used.
 | 
				
			||||||
 | 
					#html_search_scorer = 'scorer.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Output file base name for HTML help builder.
 | 
				
			||||||
 | 
					htmlhelp_basename = 'zulip-contributor-docsdoc'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup(app):
 | 
				
			||||||
 | 
					    # overrides for wide tables in RTD theme
 | 
				
			||||||
 | 
					    app.add_stylesheet('theme_overrides.css')   # path relative to _static
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -- Options for LaTeX output ---------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					latex_elements = {
 | 
				
			||||||
 | 
					# The paper size ('letterpaper' or 'a4paper').
 | 
				
			||||||
 | 
					#'papersize': 'letterpaper',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The font size ('10pt', '11pt' or '12pt').
 | 
				
			||||||
 | 
					#'pointsize': '10pt',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Additional stuff for the LaTeX preamble.
 | 
				
			||||||
 | 
					#'preamble': '',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Latex figure (float) alignment
 | 
				
			||||||
 | 
					#'figure_align': 'htbp',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Grouping the document tree into LaTeX files. List of tuples
 | 
				
			||||||
 | 
					# (source start file, target name, title,
 | 
				
			||||||
 | 
					#  author, documentclass [howto, manual, or own class]).
 | 
				
			||||||
 | 
					latex_documents = [
 | 
				
			||||||
 | 
					  (master_doc, 'zulip-contributor-docs.tex', u'Zulip Documentation',
 | 
				
			||||||
 | 
					   u'The Zulip Team', 'manual'),
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The name of an image file (relative to this directory) to place at the top of
 | 
				
			||||||
 | 
					# the title page.
 | 
				
			||||||
 | 
					#latex_logo = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# For "manual" documents, if this is true, then toplevel headings are parts,
 | 
				
			||||||
 | 
					# not chapters.
 | 
				
			||||||
 | 
					#latex_use_parts = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, show page references after internal links.
 | 
				
			||||||
 | 
					#latex_show_pagerefs = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, show URL addresses after external links.
 | 
				
			||||||
 | 
					#latex_show_urls = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Documents to append as an appendix to all manuals.
 | 
				
			||||||
 | 
					#latex_appendices = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If false, no module index is generated.
 | 
				
			||||||
 | 
					#latex_domain_indices = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -- Options for manual page output ---------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# One entry per manual page. List of tuples
 | 
				
			||||||
 | 
					# (source start file, name, description, authors, manual section).
 | 
				
			||||||
 | 
					man_pages = [
 | 
				
			||||||
 | 
					    (master_doc, 'zulip-contributor-docs', u'Zulip Documentation',
 | 
				
			||||||
 | 
					     [author], 1)
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, show URL addresses after external links.
 | 
				
			||||||
 | 
					#man_show_urls = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -- Options for Texinfo output -------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Grouping the document tree into Texinfo files. List of tuples
 | 
				
			||||||
 | 
					# (source start file, target name, title, author,
 | 
				
			||||||
 | 
					#  dir menu entry, description, category)
 | 
				
			||||||
 | 
					texinfo_documents = [
 | 
				
			||||||
 | 
					  (master_doc, 'zulip-contributor-docs', u'Zulip Documentation',
 | 
				
			||||||
 | 
					   author, 'zulip-contributor-docs', 'Documentation for contributing to Zulip.',
 | 
				
			||||||
 | 
					   'Miscellaneous'),
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Documents to append as an appendix to all manuals.
 | 
				
			||||||
 | 
					#texinfo_appendices = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If false, no module index is generated.
 | 
				
			||||||
 | 
					#texinfo_domain_indices = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# How to display URL addresses: 'footnote', 'no', or 'inline'.
 | 
				
			||||||
 | 
					#texinfo_show_urls = 'footnote'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If true, do not generate a @detailmenu in the "Top" node's menu.
 | 
				
			||||||
 | 
					#texinfo_no_detailmenu = False
 | 
				
			||||||
							
								
								
									
										95
									
								
								docs/directory-structure.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								docs/directory-structure.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					===================
 | 
				
			||||||
 | 
					Directory structure
 | 
				
			||||||
 | 
					===================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This page documents the Zulip directory structure and how to decide where to
 | 
				
			||||||
 | 
					put a file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Scripts
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+--------------------+-----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``scripts/``       | Scripts that production deployments might run manually (e.g. ``restart-server``)  |
 | 
				
			||||||
 | 
					+--------------------+-----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``bin/``           | Scripts that are needed on production deployments but humans should never run     |
 | 
				
			||||||
 | 
					+--------------------+-----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``scripts/setup/`` | Tools that production deployments will only run once, during installation         |
 | 
				
			||||||
 | 
					+--------------------+-----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``tools/``         | Development tools                                                                 |
 | 
				
			||||||
 | 
					+--------------------+-----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bots
 | 
				
			||||||
 | 
					====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+------------------------+----------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``api/integrations``   | Bots distributed as part of the Zulip API bundle.                    |
 | 
				
			||||||
 | 
					+------------------------+----------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``bots/``              | Previously Zulip internal bots.  These usually need a bit of work.   |
 | 
				
			||||||
 | 
					+------------------------+----------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Management commands
 | 
				
			||||||
 | 
					===================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/management/commands/``     | Management commands one might run at a production deployment site (e.g. scripts to change a value or deactivate a user properly)   |
 | 
				
			||||||
 | 
					+-------------------------------------+------------------------------------------------------------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Views
 | 
				
			||||||
 | 
					=====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+--------------------------------+-----------------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/tornadoviews.py``     | Tornado views                           |
 | 
				
			||||||
 | 
					+--------------------------------+-----------------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/views/webhooks.py``   | Webhook views                           |
 | 
				
			||||||
 | 
					+--------------------------------+-----------------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/views/messages.py``   | message-related views                   |
 | 
				
			||||||
 | 
					+--------------------------------+-----------------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/views/__init__.py``   | other Django views                      |
 | 
				
			||||||
 | 
					+--------------------------------+-----------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Static assets
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+---------------+---------------------------------------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``assets/``   | For assets not to be served to the web (e.g. the system to generate our favicons)                             |
 | 
				
			||||||
 | 
					+---------------+---------------------------------------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``static/``   | For things we do want to both serve to the web and distribute to production deployments (e.g. the webpages)   |
 | 
				
			||||||
 | 
					+---------------+---------------------------------------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Puppet
 | 
				
			||||||
 | 
					======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+--------------------+----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``puppet/zulip``   | For configuration for production deployments                                     |
 | 
				
			||||||
 | 
					+--------------------+----------------------------------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Templates
 | 
				
			||||||
 | 
					=========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+--------------------------+--------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``templates/zerver``     | For templates related to zerver views                  |
 | 
				
			||||||
 | 
					+--------------------------+--------------------------------------------------------+
 | 
				
			||||||
 | 
					| ``static/templates``     | Handlebars templates for the frontend                  |
 | 
				
			||||||
 | 
					+--------------------------+--------------------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tests
 | 
				
			||||||
 | 
					=====
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+------------------------+-----------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/test*.py``             | Backend tests            |       |
 | 
				
			||||||
 | 
					+------------------------+-----------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/tests/frontend/node``  | Node Frontend unit tests |
 | 
				
			||||||
 | 
					+------------------------+-----------------------------------+
 | 
				
			||||||
 | 
					| ``zerver/tests/frontend/tests`` | Casper frontend tests    |
 | 
				
			||||||
 | 
					+------------------------+-----------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Documentation
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+-------------+-----------------------------------------------+
 | 
				
			||||||
 | 
					| ``docs/``   | Source for this documentation                 |
 | 
				
			||||||
 | 
					+-------------+-----------------------------------------------+
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can consult the repository's .gitattributes file to see exactly
 | 
				
			||||||
 | 
					which components are excluded from production releases (release
 | 
				
			||||||
 | 
					tarballs are generated using tools/build-release-tarball).
 | 
				
			||||||
							
								
								
									
										9
									
								
								docs/html_unescape.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										9
									
								
								docs/html_unescape.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Remove HTML entity escaping left over from MediaWiki->rST conversion.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import html
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for line in sys.stdin:
 | 
				
			||||||
 | 
					    print(html.unescape(line), end='')
 | 
				
			||||||
							
								
								
									
										25
									
								
								docs/index.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								docs/index.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					.. zulip documentation master file, created by
 | 
				
			||||||
 | 
					   sphinx-quickstart on Mon Aug 17 16:24:04 2015.
 | 
				
			||||||
 | 
					   You can adapt this file completely to your liking, but it should at least
 | 
				
			||||||
 | 
					   contain the root `toctree` directive.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Welcome to Zulip documentation!
 | 
				
			||||||
 | 
					===============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Contents:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. toctree::
 | 
				
			||||||
 | 
					   :maxdepth: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   new-feature-tutorial
 | 
				
			||||||
 | 
					   code-style
 | 
				
			||||||
 | 
					   directory-structure
 | 
				
			||||||
 | 
					   testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Indices and tables
 | 
				
			||||||
 | 
					==================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* :ref:`genindex`
 | 
				
			||||||
 | 
					* :ref:`modindex`
 | 
				
			||||||
 | 
					* :ref:`search`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										85
									
								
								docs/new-feature-tutorial.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								docs/new-feature-tutorial.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
				
			|||||||
 | 
					====================
 | 
				
			||||||
 | 
					New Feature Tutorial
 | 
				
			||||||
 | 
					====================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. attention::
 | 
				
			||||||
 | 
					   This tutorial is an unfinished work -- contributions welcome!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The changes needed to add a new feature will vary, of course.  We give an
 | 
				
			||||||
 | 
					example here that illustrates some of the common steps needed.  We describe
 | 
				
			||||||
 | 
					the process of adding a new setting for admins that restricts inviting new
 | 
				
			||||||
 | 
					users to admins only.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Backend Changes
 | 
				
			||||||
 | 
					===============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Adding a field to the database
 | 
				
			||||||
 | 
					------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The server accesses the underlying database in `zerver/models.py`.  Add
 | 
				
			||||||
 | 
					a new field in the appropriate class, `realm_invite_by_admins_only`
 | 
				
			||||||
 | 
					in the `Realm` class in this case.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once you do so, you need to create the migration and run it; the
 | 
				
			||||||
 | 
					process is documented at:
 | 
				
			||||||
 | 
					https://docs.djangoproject.com/en/1.8/topics/migrations/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once you've run the migration, to test your changes, you'll want to
 | 
				
			||||||
 | 
					restart memcached on your development server (``/etc/init.d/memcached restart``) and
 | 
				
			||||||
 | 
					then restart ``run-dev.py`` to avoid interacting with cached objects.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Backend changes
 | 
				
			||||||
 | 
					---------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should add code in `zerver/lib/actions.py` to interact with the database,
 | 
				
			||||||
 | 
					that actually updates the relevant field.  In this case, `do_set_realm_invite_by_admins_only`
 | 
				
			||||||
 | 
					is a function that actually updates the field in the database, and sends
 | 
				
			||||||
 | 
					an event announcing that this change has been made.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You then need update the `fetch_initial_state_data` and `apply_events` functions
 | 
				
			||||||
 | 
					in `zerver/lib/actions.py` to update the state based on the event you just created.
 | 
				
			||||||
 | 
					In this case, we add a line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  state['realm_invite_by_admins_only'] = user_profile.realm.invite_by_admins_only`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					to the `fetch_initial_state_data` function.  The `apply_events` function
 | 
				
			||||||
 | 
					doesn't need to be updated since
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   elif event['type'] == 'realm':
 | 
				
			||||||
 | 
					       field = 'realm_' + event['property']
 | 
				
			||||||
 | 
					       state[field] = event['value']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					already took care of our event.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then update `zerver/views/__init__.py` to actually call your function.
 | 
				
			||||||
 | 
					In the dictionary which sets the javascript `page_params` dictionary,
 | 
				
			||||||
 | 
					add a value for your feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   realm_invite_by_admins_only = register_ret['realm_invite_by_admins_only']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Perhaps your new option controls some other backend rendering: in our case
 | 
				
			||||||
 | 
					we test for this option in the `home` method for adding a variable to the response.
 | 
				
			||||||
 | 
					The functions in this file control the generation of various pages served
 | 
				
			||||||
 | 
					(along with the Django templates).
 | 
				
			||||||
 | 
					Our new feature also shows up in the administration tab (as a checkbox),
 | 
				
			||||||
 | 
					so we need to update the `update_realm` function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, add tests for your backend changes; at the very least you
 | 
				
			||||||
 | 
					should add a test of your event data flowing through the system in
 | 
				
			||||||
 | 
					``test_events.py``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Frontend changes
 | 
				
			||||||
 | 
					----------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You need to change various things on the front end.  In this case, the relevant files
 | 
				
			||||||
 | 
					are `static/js/server_events.js`, `static/js/admin.js`, `static/styles/zulip.css
 | 
				
			||||||
 | 
					and `static/templates/admin_tab.handlebars`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										1
									
								
								docs/requirements.readthedocs.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								docs/requirements.readthedocs.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					# Empty requirements.txt to avoid readthedocs installing all our dependencies.
 | 
				
			||||||
							
								
								
									
										251
									
								
								docs/testing.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								docs/testing.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,251 @@
 | 
				
			|||||||
 | 
					=======
 | 
				
			||||||
 | 
					Testing
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Running tests
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To run everything, just use ``./tools/test-all``. This runs lint checks,
 | 
				
			||||||
 | 
					web frontend / whole-system blackbox tests, and backend Django tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you want to run individual parts, see the various commands inside
 | 
				
			||||||
 | 
					that script.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Schema and initial data changes
 | 
				
			||||||
 | 
					-------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you change the database schema or change the initial test data, you
 | 
				
			||||||
 | 
					have have to regenerate the pristine test database by running
 | 
				
			||||||
 | 
					``tools/do-destroy-rebuild-test-database``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wiping the test databases
 | 
				
			||||||
 | 
					-------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You should first try running: ``tools/do-destroy-rebuild-test-database``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If that fails you should try to do:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sudo -u postgres psql
 | 
				
			||||||
 | 
					    > DROP DATABASE zulip_test;
 | 
				
			||||||
 | 
					    > DROP DATABASE zulip_test_template;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					and then run ``tools/do-destroy-rebuild-test-database``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Recreating the postgres cluster
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. warning::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   **This is irreversible, so do it with care, and never do this anywhere
 | 
				
			||||||
 | 
					   in production.**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If your postgres cluster (collection of databases) gets totally trashed
 | 
				
			||||||
 | 
					permissions-wise, and you can't otherwise repair it, you can recreate
 | 
				
			||||||
 | 
					it. On Ubuntu:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sudo pg_dropcluster --stop 9.1 main
 | 
				
			||||||
 | 
					    sudo pg_createcluster --locale=en_US.utf8 --start 9.1 main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Backend Django tests
 | 
				
			||||||
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These live in ``zerver/tests.py`` and ``zerver/test_*.py``. Run them
 | 
				
			||||||
 | 
					with ``tools/test-backend``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Web frontend black-box tests
 | 
				
			||||||
 | 
					----------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These live in ``zerver/tests/frontend/tests/``. This is a "black box"
 | 
				
			||||||
 | 
					test; we load the frontend in a real (headless) browser, from a real dev
 | 
				
			||||||
 | 
					server, and simulate UI interactions like sending messages, narrowing,
 | 
				
			||||||
 | 
					etc.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since this is interacting with a real dev server, it can catch backend
 | 
				
			||||||
 | 
					bugs as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can run this with ``./zerver/tests/frontend/run``. You will need
 | 
				
			||||||
 | 
					`PhantomJS <http://phantomjs.org/>`__ 1.7.0 or later.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Debugging Casper.JS
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Casper.js (via PhantomJS) has support for remote debugging. However, it
 | 
				
			||||||
 | 
					is not perfect. Here are some steps for using it and gotchas you might
 | 
				
			||||||
 | 
					want to know.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To turn on remote debugging, pass ``--remote-debug`` to the
 | 
				
			||||||
 | 
					``./zerver/frontend/tests/run`` script. This will run the tests with
 | 
				
			||||||
 | 
					port ``7777`` open for remote debugging. You can now connect to
 | 
				
			||||||
 | 
					``localhost:7777`` in a Webkit browser. Somewhat recent versions of
 | 
				
			||||||
 | 
					Chrome or Safari might be required.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  When connecting to the remote debugger, you will see a list of pages,
 | 
				
			||||||
 | 
					   probably 2. One page called ``about:blank`` is the headless page in
 | 
				
			||||||
 | 
					   which the CasperJS test itself is actually running in. This is where
 | 
				
			||||||
 | 
					   your test code is.
 | 
				
			||||||
 | 
					-  The other page, probably ``localhost:9981``, is the Zulip page that
 | 
				
			||||||
 | 
					   the test is testing---that is, the page running our app that our test
 | 
				
			||||||
 | 
					   is exercising.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Since the tests are now running, you can open the ``about:blank`` page,
 | 
				
			||||||
 | 
					switch to the Scripts tab, and open the running ``0x-foo.js`` test. If
 | 
				
			||||||
 | 
					you set a breakpoint and it is hit, the inspector will pause and you can
 | 
				
			||||||
 | 
					do your normal JS debugging. You can also put breakpoints in the Zulip
 | 
				
			||||||
 | 
					webpage itself if you wish to inspect the state of the Zulip frontend.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Web frontend unit tests
 | 
				
			||||||
 | 
					-----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As an alternative to the black-box whole-app testing, you can unit test
 | 
				
			||||||
 | 
					individual JavaScript files that use the module pattern. For example, to
 | 
				
			||||||
 | 
					test the ``foobar.js`` file, you would first add the following to the
 | 
				
			||||||
 | 
					bottom of ``foobar.js``:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     if (typeof module !== 'undefined') {
 | 
				
			||||||
 | 
					         module.exports = foobar;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This makes ``foobar.js`` follow the CommonJS module pattern, so it can
 | 
				
			||||||
 | 
					be required in Node.js, which runs our tests.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now create ``zerver/tests/frontend/node/foobar.js``. At the top, require
 | 
				
			||||||
 | 
					the `Node.js assert module <http://nodejs.org/api/assert.html>`__, and
 | 
				
			||||||
 | 
					the module you're testing, like so:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     var assert = require('assert');
 | 
				
			||||||
 | 
					     var foobar = require('js/foobar.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(If the module you're testing depends on other modules, or modifies
 | 
				
			||||||
 | 
					global state, you need to also read `the next section`__.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__ handling-dependencies_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Define and call some tests using the `assert
 | 
				
			||||||
 | 
					module <http://nodejs.org/api/assert.html>`__. Note that for "equal"
 | 
				
			||||||
 | 
					asserts, the *actual* value comes first, the *expected* value second.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     (function test_somefeature() {
 | 
				
			||||||
 | 
					         assert.strictEqual(foobar.somefeature('baz'), 'quux');
 | 
				
			||||||
 | 
					         assert.throws(foobar.somefeature('Invalid Input'));
 | 
				
			||||||
 | 
					     }());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The test runner (index.js) automatically runs all .js files in the
 | 
				
			||||||
 | 
					zerver/tests/frontend/node directory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.. _handling-dependencies:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Handling dependencies in tests
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The following scheme helps avoid tests leaking globals between each
 | 
				
			||||||
 | 
					other.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First, if you can avoid globals, do it, and the code that is directly
 | 
				
			||||||
 | 
					under test can simply be handled like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        var search = require('js/search_suggestion.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For deeper dependencies, you want to categorize each module as follows:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-  Exercise the module's real code for deeper, more realistic testing?
 | 
				
			||||||
 | 
					-  Stub out the module's interface for more control, speed, and
 | 
				
			||||||
 | 
					   isolation?
 | 
				
			||||||
 | 
					-  Do some combination of the above?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For all the modules where you want to run actual code, add a statement
 | 
				
			||||||
 | 
					like the following to the top of your test file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     add_dependencies({
 | 
				
			||||||
 | 
					         _: 'third/underscore/underscore.js',
 | 
				
			||||||
 | 
					         util: 'js/util.js',
 | 
				
			||||||
 | 
					         Dict: 'js/dict.js',
 | 
				
			||||||
 | 
					         Handlebars: 'handlebars',
 | 
				
			||||||
 | 
					         Filter: 'js/filter.js',
 | 
				
			||||||
 | 
					         typeahead_helper: 'js/typeahead_helper.js',
 | 
				
			||||||
 | 
					         stream_data: 'js/stream_data.js',
 | 
				
			||||||
 | 
					         narrow: 'js/narrow.js'
 | 
				
			||||||
 | 
					     });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For modules that you want to completely stub out, please use a pattern
 | 
				
			||||||
 | 
					like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     set_global('page_params', {
 | 
				
			||||||
 | 
					         email: 'bob@zulip.com'
 | 
				
			||||||
 | 
					     });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // then maybe further down
 | 
				
			||||||
 | 
					     global.page_params.email = 'alice@zulip.com';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Finally, there's the hybrid situation, where you want to borrow some of
 | 
				
			||||||
 | 
					a module's real functionality but stub out other pieces. Obviously, this
 | 
				
			||||||
 | 
					is a pretty strong smell that the other module might be lacking in
 | 
				
			||||||
 | 
					cohesion, but that code might be outside your jurisdiction. The pattern
 | 
				
			||||||
 | 
					here is this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // Use real versions of parse/unparse
 | 
				
			||||||
 | 
					     var narrow = require('js/narrow.js');
 | 
				
			||||||
 | 
					     set_global('narrow', {
 | 
				
			||||||
 | 
					         parse: narrow.parse,
 | 
				
			||||||
 | 
					         unparse: narrow.unparse
 | 
				
			||||||
 | 
					     });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     // But later, I want to stub the stream without having to call super-expensive
 | 
				
			||||||
 | 
					     // real code like narrow.activate().
 | 
				
			||||||
 | 
					     global.narrow.stream = function () {
 | 
				
			||||||
 | 
					         return 'office';
 | 
				
			||||||
 | 
					     };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Coverage reports
 | 
				
			||||||
 | 
					~~~~~~~~~~~~~~~~
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can automatically generate coverage reports for the JavaScript unit
 | 
				
			||||||
 | 
					tests. To do so, install istanbul:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     sudo npm install -g istanbul
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And run test-js-with-node with the 'cover' parameter:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					     tools/test-js-with-node cover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then open ``coverage/lcov-report/js/index.html`` in your browser.
 | 
				
			||||||
 | 
					Modules we don't test *at all* aren't listed in the report, so this
 | 
				
			||||||
 | 
					tends to overstate how good our overall coverage is, but it's accurate
 | 
				
			||||||
 | 
					for individual files. You can also click a filename to see the specific
 | 
				
			||||||
 | 
					statements and branches not tested. 100% branch coverage isn't
 | 
				
			||||||
 | 
					necessarily possible, but getting to at least 80% branch coverage is a
 | 
				
			||||||
 | 
					good goal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Manual testing (local app + web browser)
 | 
				
			||||||
 | 
					========================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Setting up the manual testing database
 | 
				
			||||||
 | 
					--------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ./tools/do-destroy-rebuild-database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Will populate your local database with all the usual accounts plus some
 | 
				
			||||||
 | 
					test messages involving Shakespeare characters.
 | 
				
			||||||
@@ -1 +0,0 @@
 | 
				
			|||||||
../zproject/backends.py
 | 
					 | 
				
			||||||
							
								
								
									
										169
									
								
								provision.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								provision.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					import os
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import logging
 | 
				
			||||||
 | 
					import platform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    import sh
 | 
				
			||||||
 | 
					except ImportError:
 | 
				
			||||||
 | 
					    import pbs as sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SUPPORTED_PLATFORMS = {
 | 
				
			||||||
 | 
					    "Ubuntu": [
 | 
				
			||||||
 | 
					        "trusty",
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					APT_DEPENDENCIES = {
 | 
				
			||||||
 | 
					    "trusty": [
 | 
				
			||||||
 | 
					        "closure-compiler",
 | 
				
			||||||
 | 
					        "libffi-dev",
 | 
				
			||||||
 | 
					        "memcached",
 | 
				
			||||||
 | 
					        "rabbitmq-server",
 | 
				
			||||||
 | 
					        "libldap2-dev",
 | 
				
			||||||
 | 
					        "redis-server",
 | 
				
			||||||
 | 
					        "postgresql-server-dev-all",
 | 
				
			||||||
 | 
					        "libmemcached-dev",
 | 
				
			||||||
 | 
					        "postgresql-9.3",
 | 
				
			||||||
 | 
					        "python-dev",
 | 
				
			||||||
 | 
					        "hunspell-en-us",
 | 
				
			||||||
 | 
					        "nodejs",
 | 
				
			||||||
 | 
					        "python-virtualenv",
 | 
				
			||||||
 | 
					        "supervisor",
 | 
				
			||||||
 | 
					        "git",
 | 
				
			||||||
 | 
					        "npm",
 | 
				
			||||||
 | 
					        "node-jquery",
 | 
				
			||||||
 | 
					        "yui-compressor",
 | 
				
			||||||
 | 
					        "puppet",               # Used by lint-all
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: backport node-{cssstyle,htmlparser2,nwmatcher} to trusty,
 | 
				
			||||||
 | 
					# so we can eliminate npm (above) and this section.
 | 
				
			||||||
 | 
					NPM_DEPENDENCIES = {
 | 
				
			||||||
 | 
					    "trusty": [
 | 
				
			||||||
 | 
					        "cssstyle",
 | 
				
			||||||
 | 
					        "htmlparser2",
 | 
				
			||||||
 | 
					        "nwmatcher",
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VENV_PATH="/srv/zulip-venv"
 | 
				
			||||||
 | 
					ZULIP_PATH="/srv/zulip"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# tsearch-extras is an extension to postgres's built-in full-text search.
 | 
				
			||||||
 | 
					# TODO: use a real APT repository
 | 
				
			||||||
 | 
					TSEARCH_URL_BASE = "https://dl.dropboxusercontent.com/u/283158365/zuliposs/"
 | 
				
			||||||
 | 
					TSEARCH_PACKAGE_NAME = {
 | 
				
			||||||
 | 
					    "trusty": "postgresql-9.3-tsearch-extras"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					TSEARCH_VERSION = "0.1.2"
 | 
				
			||||||
 | 
					# TODO: this path is platform-specific!
 | 
				
			||||||
 | 
					TSEARCH_STOPWORDS_PATH = "/usr/share/postgresql/9.3/tsearch_data/"
 | 
				
			||||||
 | 
					REPO_STOPWORDS_PATH = os.path.join(
 | 
				
			||||||
 | 
					    ZULIP_PATH,
 | 
				
			||||||
 | 
					    "puppet",
 | 
				
			||||||
 | 
					    "zulip",
 | 
				
			||||||
 | 
					    "files",
 | 
				
			||||||
 | 
					    "postgresql",
 | 
				
			||||||
 | 
					    "zulip_english.stop",
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LOUD = dict(_out=sys.stdout, _err=sys.stderr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    log = logging.getLogger("zulip-provisioner")
 | 
				
			||||||
 | 
					    # TODO: support other architectures
 | 
				
			||||||
 | 
					    if platform.architecture()[0] == '64bit':
 | 
				
			||||||
 | 
					        arch = 'amd64'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        log.critical("Only amd64 is supported.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    vendor, version, codename = platform.dist()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not (vendor in SUPPORTED_PLATFORMS and codename in SUPPORTED_PLATFORMS[vendor]):
 | 
				
			||||||
 | 
					        log.critical("Unsupported platform: {} {}".format(vendor, codename))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        sh.apt_get.update(**LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        sh.apt_get.install(*APT_DEPENDENCIES["trusty"], assume_yes=True, **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    temp_deb_path = sh.mktemp("package_XXXXXX.deb", tmpdir=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sh.wget(
 | 
				
			||||||
 | 
					        "{}/{}_{}_{}.deb".format(
 | 
				
			||||||
 | 
					            TSEARCH_URL_BASE,
 | 
				
			||||||
 | 
					            TSEARCH_PACKAGE_NAME["trusty"],
 | 
				
			||||||
 | 
					            TSEARCH_VERSION,
 | 
				
			||||||
 | 
					            arch,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        output_document=temp_deb_path,
 | 
				
			||||||
 | 
					        **LOUD
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        sh.dpkg("--install", temp_deb_path, **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        PHANTOMJS_PATH = "/srv/phantomjs"
 | 
				
			||||||
 | 
					        PHANTOMJS_TARBALL = os.path.join(PHANTOMJS_PATH, "phantomjs-1.9.8-linux-x86_64.tar.bz2")
 | 
				
			||||||
 | 
					        sh.mkdir("-p", PHANTOMJS_PATH, **LOUD)
 | 
				
			||||||
 | 
					        sh.wget("https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.8-linux-x86_64.tar.bz2",
 | 
				
			||||||
 | 
					                output_document=PHANTOMJS_TARBALL, **LOUD)
 | 
				
			||||||
 | 
					        sh.tar("xj", directory=PHANTOMJS_PATH, file=PHANTOMJS_TARBALL, **LOUD)
 | 
				
			||||||
 | 
					        sh.ln("-sf", os.path.join(PHANTOMJS_PATH, "phantomjs-1.9.8-linux-x86_64", "bin", "phantomjs"),
 | 
				
			||||||
 | 
					              "/usr/local/bin/phantomjs", **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        sh.rm("-rf", VENV_PATH, **LOUD)
 | 
				
			||||||
 | 
					        sh.mkdir("-p", VENV_PATH, **LOUD)
 | 
				
			||||||
 | 
					        sh.chown("{}:{}".format(os.getuid(), os.getgid()), VENV_PATH, **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sh.virtualenv(VENV_PATH, **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Add the ./tools and ./scripts/setup directories inside the repository root to
 | 
				
			||||||
 | 
					    # the system path; we'll reference them later.
 | 
				
			||||||
 | 
					    orig_path = os.environ["PATH"]
 | 
				
			||||||
 | 
					    os.environ["PATH"] = os.pathsep.join((
 | 
				
			||||||
 | 
					            os.path.join(ZULIP_PATH, "tools"),
 | 
				
			||||||
 | 
					            os.path.join(ZULIP_PATH, "scripts", "setup"),
 | 
				
			||||||
 | 
					            orig_path
 | 
				
			||||||
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Put Python virtualenv activation in our .bash_profile.
 | 
				
			||||||
 | 
					    with open(os.path.expanduser('~/.bash_profile'), 'w+') as bash_profile:
 | 
				
			||||||
 | 
					        bash_profile.writelines([
 | 
				
			||||||
 | 
					            "source .bashrc\n",
 | 
				
			||||||
 | 
					            "source %s\n" % (os.path.join(VENV_PATH, "bin", "activate"),),
 | 
				
			||||||
 | 
					        ])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Switch current Python context to the virtualenv.
 | 
				
			||||||
 | 
					    activate_this = os.path.join(VENV_PATH, "bin", "activate_this.py")
 | 
				
			||||||
 | 
					    execfile(activate_this, dict(__file__=activate_this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sh.pip.install(requirement=os.path.join(ZULIP_PATH, "requirements.txt"), **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        sh.cp(REPO_STOPWORDS_PATH, TSEARCH_STOPWORDS_PATH, **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Add additional node packages for test-js-with-node.
 | 
				
			||||||
 | 
					    with sh.sudo:
 | 
				
			||||||
 | 
					        sh.npm.install(*NPM_DEPENDENCIES["trusty"], g=True, prefix="/usr", **LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Management commands expect to be run from the root of the project.
 | 
				
			||||||
 | 
					    os.chdir(ZULIP_PATH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    os.system("tools/download-zxcvbn")
 | 
				
			||||||
 | 
					    os.system("tools/emoji_dump/build_emoji")
 | 
				
			||||||
 | 
					    os.system("generate_secrets.py -d")
 | 
				
			||||||
 | 
					    sh.configure_rabbitmq(**LOUD)
 | 
				
			||||||
 | 
					    sh.postgres_init_db(**LOUD)
 | 
				
			||||||
 | 
					    sh.do_destroy_rebuild_database(**LOUD)
 | 
				
			||||||
 | 
					    sh.postgres_init_test_db(**LOUD)
 | 
				
			||||||
 | 
					    sh.do_destroy_rebuild_test_database(**LOUD)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    sys.exit(main())
 | 
				
			||||||
@@ -32,8 +32,8 @@ Listen 127.0.0.1:8888
 | 
				
			|||||||
	# You shouldn't need to edit anything below this line.
 | 
						# You shouldn't need to edit anything below this line.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	SSLEngine On
 | 
						SSLEngine On
 | 
				
			||||||
	SSLCertificateFile /etc/ssl/certs/zulip-enterprise.combined-chain.crt
 | 
						SSLCertificateFile /etc/ssl/certs/zulip.combined-chain.crt
 | 
				
			||||||
	SSLCertificateKeyFile /etc/ssl/private/zulip-enterprise.key
 | 
						SSLCertificateKeyFile /etc/ssl/private/zulip.key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WSGIScriptAlias / /home/zulip/deployments/current/zproject/wsgi.py
 | 
						WSGIScriptAlias / /home/zulip/deployments/current/zproject/wsgi.py
 | 
				
			||||||
	WSGIDaemonProcess zulip threads=5 user=zulip python-path=/home/zulip/deployments/current/
 | 
						WSGIDaemonProcess zulip threads=5 user=zulip python-path=/home/zulip/deployments/current/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,5 +54,7 @@
 | 
				
			|||||||
#@student        -       maxlogins       4
 | 
					#@student        -       maxlogins       4
 | 
				
			||||||
zulip		 soft	 nofile		 40000
 | 
					zulip		 soft	 nofile		 40000
 | 
				
			||||||
zulip		 hard	 nofile		 50000
 | 
					zulip		 hard	 nofile		 50000
 | 
				
			||||||
 | 
					root		 soft	 nofile		 40000
 | 
				
			||||||
 | 
					root		 hard	 nofile		 50000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# End of file
 | 
					# End of file
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,6 +36,10 @@ http {
 | 
				
			|||||||
        default upgrade;
 | 
					        default upgrade;
 | 
				
			||||||
        ''      close;
 | 
					        ''      close;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    # These are the official ciphers as of 2014-10-14
 | 
				
			||||||
 | 
					    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 | 
				
			||||||
 | 
					    ssl_ciphers  EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:EECDH+RC4:RSA+RC4:!MD5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    include /etc/nginx/conf.d/*.conf;
 | 
					    include /etc/nginx/conf.d/*.conf;
 | 
				
			||||||
    include /etc/nginx/sites-enabled/*;
 | 
					    include /etc/nginx/sites-enabled/*;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,10 +9,8 @@ server {
 | 
				
			|||||||
    listen 443;
 | 
					    listen 443;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ssl on;
 | 
					    ssl on;
 | 
				
			||||||
    ssl_certificate /etc/ssl/certs/zulip-enterprise.combined-chain.crt;
 | 
					    ssl_certificate /etc/ssl/certs/zulip.combined-chain.crt;
 | 
				
			||||||
    ssl_certificate_key /etc/ssl/private/zulip-enterprise.key;
 | 
					    ssl_certificate_key /etc/ssl/private/zulip.key;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    add_header X-Frame-Options DENY;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    location /user_uploads {
 | 
					    location /user_uploads {
 | 
				
			||||||
        add_header X-Content-Type-Options nosniff;
 | 
					        add_header X-Content-Type-Options nosniff;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,13 +14,36 @@ location /static/ {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Send longpoll requests to Tornado
 | 
					# Send longpoll requests to Tornado
 | 
				
			||||||
location ~ /json/get_events|/json/events|/api/v1/events {
 | 
					location ~ /json/get_events|/json/events {
 | 
				
			||||||
    proxy_pass http://tornado;
 | 
					    proxy_pass http://tornado;
 | 
				
			||||||
    include /etc/nginx/zulip-include/proxy_longpolling;
 | 
					    include /etc/nginx/zulip-include/proxy_longpolling;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proxy_set_header X-Real-IP       $remote_addr;
 | 
					    proxy_set_header X-Real-IP       $remote_addr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Send longpoll requests to Tornado
 | 
				
			||||||
 | 
					location /api/v1/events {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Origin *;
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Headers Authorization;
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Methods 'GET, POST';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($request_method = 'OPTIONS') {
 | 
				
			||||||
 | 
					        add_header Access-Control-Allow-Origin *;
 | 
				
			||||||
 | 
					        add_header Access-Control-Allow-Headers Authorization;
 | 
				
			||||||
 | 
					        add_header Access-Control-Allow-Methods 'GET, POST';
 | 
				
			||||||
 | 
					        add_header 'Content-Type' 'text/plain charset=UTF-8';
 | 
				
			||||||
 | 
					        add_header 'Content-Length' 0;
 | 
				
			||||||
 | 
					        return 204;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    proxy_pass http://tornado;
 | 
				
			||||||
 | 
					    include /etc/nginx/zulip-include/proxy_longpolling;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    proxy_set_header X-Real-IP       $remote_addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Send sockjs requests to Tornado
 | 
					# Send sockjs requests to Tornado
 | 
				
			||||||
location /sockjs {
 | 
					location /sockjs {
 | 
				
			||||||
    proxy_pass http://tornado;
 | 
					    proxy_pass http://tornado;
 | 
				
			||||||
@@ -38,4 +61,19 @@ location / {
 | 
				
			|||||||
    fastcgi_next_upstream off;
 | 
					    fastcgi_next_upstream off;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					location /api/ {
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Origin *;
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Headers Authorization;
 | 
				
			||||||
 | 
					    add_header Access-Control-Allow-Methods 'GET, POST';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    include fastcgi_params;
 | 
				
			||||||
 | 
					    fastcgi_pass django;
 | 
				
			||||||
 | 
					    fastcgi_split_path_info ^()(.*)$;
 | 
				
			||||||
 | 
					    # Second number set to `getconf PAGESIZE`
 | 
				
			||||||
 | 
					    fastcgi_buffers 1024 4k;
 | 
				
			||||||
 | 
					    fastcgi_max_temp_file_size 0;
 | 
				
			||||||
 | 
					    fastcgi_next_upstream off;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
include /etc/nginx/zulip-include/app.d/*.conf;
 | 
					include /etc/nginx/zulip-include/app.d/*.conf;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
/.*\+.*@.*/ zulip@localhost
 | 
					/.*\+.*@.*/ zulip@localhost
 | 
				
			||||||
 | 
					/^mm.*/ zulip@localhost
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,15 +38,15 @@
 | 
				
			|||||||
# The default values of these variables are driven from the -D command-line
 | 
					# The default values of these variables are driven from the -D command-line
 | 
				
			||||||
# option or PGDATA environment variable, represented here as ConfigDir.
 | 
					# option or PGDATA environment variable, represented here as ConfigDir.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
data_directory = '/var/lib/postgresql/9.1/main'		# use data in another directory
 | 
					data_directory = '/var/lib/postgresql/9.3/main'		# use data in another directory
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
hba_file = '/etc/postgresql/9.1/main/pg_hba.conf'	# host-based authentication file
 | 
					hba_file = '/etc/postgresql/9.3/main/pg_hba.conf'	# host-based authentication file
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
ident_file = '/etc/postgresql/9.1/main/pg_ident.conf'	# ident configuration file
 | 
					ident_file = '/etc/postgresql/9.3/main/pg_ident.conf'	# ident configuration file
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If external_pid_file is not explicitly set, no extra PID file is written.
 | 
					# If external_pid_file is not explicitly set, no extra PID file is written.
 | 
				
			||||||
external_pid_file = '/var/run/postgresql/9.1-main.pid'		# write an extra PID file
 | 
					external_pid_file = '/var/run/postgresql/9.3-main.pid'		# write an extra PID file
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,7 +65,7 @@ port = 5432				# (change requires restart)
 | 
				
			|||||||
# Note:  Increasing max_connections costs ~400 bytes of shared memory per
 | 
					# Note:  Increasing max_connections costs ~400 bytes of shared memory per
 | 
				
			||||||
# connection slot, plus lock space (see max_locks_per_transaction).
 | 
					# connection slot, plus lock space (see max_locks_per_transaction).
 | 
				
			||||||
#superuser_reserved_connections = 3	# (change requires restart)
 | 
					#superuser_reserved_connections = 3	# (change requires restart)
 | 
				
			||||||
unix_socket_directory = '/var/run/postgresql'		# (change requires restart)
 | 
					unix_socket_directories = '/var/run/postgresql'		# (change requires restart)
 | 
				
			||||||
#unix_socket_group = ''			# (change requires restart)
 | 
					#unix_socket_group = ''			# (change requires restart)
 | 
				
			||||||
#unix_socket_permissions = 0777		# begin with 0 to use octal notation
 | 
					#unix_socket_permissions = 0777		# begin with 0 to use octal notation
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
@@ -77,7 +77,7 @@ unix_socket_directory = '/var/run/postgresql'		# (change requires restart)
 | 
				
			|||||||
# - Security and Authentication -
 | 
					# - Security and Authentication -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#authentication_timeout = 1min		# 1s-600s
 | 
					#authentication_timeout = 1min		# 1s-600s
 | 
				
			||||||
ssl = true				# (change requires restart)
 | 
					#ssl = true				# (change requires restart)
 | 
				
			||||||
#ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH'	# allowed SSL ciphers
 | 
					#ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH'	# allowed SSL ciphers
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
#ssl_renegotiation_limit = 512MB	# amount of data between renegotiations
 | 
					#ssl_renegotiation_limit = 512MB	# amount of data between renegotiations
 | 
				
			||||||
@@ -106,7 +106,7 @@ ssl = true				# (change requires restart)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# - Memory -
 | 
					# - Memory -
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# shared_buffers = 24MB			# min 128kB
 | 
					shared_buffers = 128MB			# min 128kB
 | 
				
			||||||
					# (change requires restart)
 | 
										# (change requires restart)
 | 
				
			||||||
#temp_buffers = 8MB			# min 800kB
 | 
					#temp_buffers = 8MB			# min 800kB
 | 
				
			||||||
#max_prepared_transactions = 0		# zero disables the feature
 | 
					#max_prepared_transactions = 0		# zero disables the feature
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
#!/usr/bin/python
 | 
					#!/usr/bin/env python
 | 
				
			||||||
import psycopg2
 | 
					import psycopg2
 | 
				
			||||||
import psycopg2.extensions
 | 
					import psycopg2.extensions
 | 
				
			||||||
import select
 | 
					import select
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,22 +0,0 @@
 | 
				
			|||||||
[main]
 | 
					 | 
				
			||||||
  server = puppet.zulip.com
 | 
					 | 
				
			||||||
  environment = production
 | 
					 | 
				
			||||||
  confdir = /etc/puppet
 | 
					 | 
				
			||||||
  logdir=/var/log/puppet
 | 
					 | 
				
			||||||
  vardir=/var/lib/puppet
 | 
					 | 
				
			||||||
  ssldir=/var/lib/puppet/ssl
 | 
					 | 
				
			||||||
  rundir=/var/run/puppet
 | 
					 | 
				
			||||||
  factpath=$vardir/lib/facter
 | 
					 | 
				
			||||||
  templatedir=$confdir/templates
 | 
					 | 
				
			||||||
  prerun_command=/etc/puppet/etckeeper-commit-pre
 | 
					 | 
				
			||||||
  postrun_command=/etc/puppet/etckeeper-commit-post
 | 
					 | 
				
			||||||
  modulepath = /root/zulip/puppet:/etc/puppet/modules:/usr/share/puppet/modules
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[master]
 | 
					 | 
				
			||||||
  environment = production
 | 
					 | 
				
			||||||
  manifest    = $confdir/environments/$environment/manifests/site.pp
 | 
					 | 
				
			||||||
  modulepath  = $confdir/environments/$environment/modules
 | 
					 | 
				
			||||||
[agent]
 | 
					 | 
				
			||||||
  report = true
 | 
					 | 
				
			||||||
  show_diff = true
 | 
					 | 
				
			||||||
  environment = production
 | 
					 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
# Redis configuration file example
 | 
					# Redis configuration file example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Note on units: when memory size is needed, it is possible to specifiy
 | 
					# Note on units: when memory size is needed, it is possible to specify
 | 
				
			||||||
# it in the usual form of 1k 5GB 4M and so forth:
 | 
					# it in the usual form of 1k 5GB 4M and so forth:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# 1k => 1000 bytes
 | 
					# 1k => 1000 bytes
 | 
				
			||||||
@@ -12,6 +12,26 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# units are case insensitive so 1GB 1Gb 1gB are all the same.
 | 
					# units are case insensitive so 1GB 1Gb 1gB are all the same.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################## INCLUDES ###################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Include one or more other config files here.  This is useful if you
 | 
				
			||||||
 | 
					# have a standard template that goes to all Redis server but also need
 | 
				
			||||||
 | 
					# to customize a few per-server settings.  Include files can include
 | 
				
			||||||
 | 
					# other files, so use this wisely.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Notice option "include" won't be rewritten by command "CONFIG REWRITE"
 | 
				
			||||||
 | 
					# from admin or Redis Sentinel. Since Redis always uses the last processed
 | 
				
			||||||
 | 
					# line as value of a configuration directive, you'd better put includes
 | 
				
			||||||
 | 
					# at the beginning of this file to avoid overwriting config change at runtime.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If instead you are interested in using includes to override configuration
 | 
				
			||||||
 | 
					# options, it is better to use include as the last line.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# include /path/to/local.conf
 | 
				
			||||||
 | 
					# include /path/to/other.conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################ GENERAL  #####################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# By default Redis does not run as a daemon. Use 'yes' if you need it.
 | 
					# By default Redis does not run as a daemon. Use 'yes' if you need it.
 | 
				
			||||||
# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
 | 
					# Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
 | 
				
			||||||
daemonize yes
 | 
					daemonize yes
 | 
				
			||||||
@@ -24,9 +44,14 @@ pidfile /var/run/redis/redis-server.pid
 | 
				
			|||||||
# If port 0 is specified Redis will not listen on a TCP socket.
 | 
					# If port 0 is specified Redis will not listen on a TCP socket.
 | 
				
			||||||
port 6379
 | 
					port 6379
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If you want you can bind a single interface, if the bind option is not
 | 
					# By default Redis listens for connections from all the network interfaces
 | 
				
			||||||
# specified all the interfaces will listen for incoming connections.
 | 
					# available on the server. It is possible to listen to just one or multiple
 | 
				
			||||||
 | 
					# interfaces using the "bind" configuration directive, followed by one or
 | 
				
			||||||
 | 
					# more IP addresses.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					# Examples:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# bind 192.168.1.100 10.0.0.1
 | 
				
			||||||
bind 127.0.0.1
 | 
					bind 127.0.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Specify the path for the unix socket that will be used to listen for
 | 
					# Specify the path for the unix socket that will be used to listen for
 | 
				
			||||||
@@ -39,15 +64,31 @@ bind 127.0.0.1
 | 
				
			|||||||
# Close the connection after a client is idle for N seconds (0 to disable)
 | 
					# Close the connection after a client is idle for N seconds (0 to disable)
 | 
				
			||||||
timeout 0
 | 
					timeout 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set server verbosity to 'debug'
 | 
					# TCP keepalive.
 | 
				
			||||||
# it can be one of:
 | 
					#
 | 
				
			||||||
 | 
					# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence
 | 
				
			||||||
 | 
					# of communication. This is useful for two reasons:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# 1) Detect dead peers.
 | 
				
			||||||
 | 
					# 2) Take the connection alive from the point of view of network
 | 
				
			||||||
 | 
					#    equipment in the middle.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# On Linux, the specified value (in seconds) is the period used to send ACKs.
 | 
				
			||||||
 | 
					# Note that to close the connection the double of the time is needed.
 | 
				
			||||||
 | 
					# On other kernels the period depends on the kernel configuration.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# A reasonable value for this option is 60 seconds.
 | 
				
			||||||
 | 
					tcp-keepalive 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Specify the server verbosity level.
 | 
				
			||||||
 | 
					# This can be one of:
 | 
				
			||||||
# debug (a lot of information, useful for development/testing)
 | 
					# debug (a lot of information, useful for development/testing)
 | 
				
			||||||
# verbose (many rarely useful info, but not a mess like the debug level)
 | 
					# verbose (many rarely useful info, but not a mess like the debug level)
 | 
				
			||||||
# notice (moderately verbose, what you want in production probably)
 | 
					# notice (moderately verbose, what you want in production probably)
 | 
				
			||||||
# warning (only very important / critical messages are logged)
 | 
					# warning (only very important / critical messages are logged)
 | 
				
			||||||
loglevel notice
 | 
					loglevel notice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Specify the log file name. Also 'stdout' can be used to force
 | 
					# Specify the log file name. Also the empty string can be used to force
 | 
				
			||||||
# Redis to log on the standard output. Note that if you use standard
 | 
					# Redis to log on the standard output. Note that if you use standard
 | 
				
			||||||
# output for logging but daemonize, logs will be sent to /dev/null
 | 
					# output for logging but daemonize, logs will be sent to /dev/null
 | 
				
			||||||
logfile /var/log/redis/redis-server.log
 | 
					logfile /var/log/redis/redis-server.log
 | 
				
			||||||
@@ -67,7 +108,7 @@ logfile /var/log/redis/redis-server.log
 | 
				
			|||||||
# dbid is a number between 0 and 'databases'-1
 | 
					# dbid is a number between 0 and 'databases'-1
 | 
				
			||||||
databases 16
 | 
					databases 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################ SNAPSHOTTING  #################################
 | 
					################################ SNAPSHOTTING  ################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Save the DB on disk:
 | 
					# Save the DB on disk:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
@@ -82,10 +123,31 @@ databases 16
 | 
				
			|||||||
#   after 60 sec if at least 10000 keys changed
 | 
					#   after 60 sec if at least 10000 keys changed
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#   Note: you can disable saving at all commenting all the "save" lines.
 | 
					#   Note: you can disable saving at all commenting all the "save" lines.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   It is also possible to remove all the previously configured save
 | 
				
			||||||
 | 
					#   points by adding a save directive with a single empty string argument
 | 
				
			||||||
 | 
					#   like in the following example:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   save ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# save 900 1
 | 
					save 900 1
 | 
				
			||||||
# save 300 10
 | 
					save 300 10
 | 
				
			||||||
# save 60 10000
 | 
					save 60 10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# By default Redis will stop accepting writes if RDB snapshots are enabled
 | 
				
			||||||
 | 
					# (at least one save point) and the latest background save failed.
 | 
				
			||||||
 | 
					# This will make the user aware (in a hard way) that data is not persisting
 | 
				
			||||||
 | 
					# on disk properly, otherwise chances are that no one will notice and some
 | 
				
			||||||
 | 
					# disaster will happen.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If the background saving process will start working again Redis will
 | 
				
			||||||
 | 
					# automatically allow writes again.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# However if you have setup your proper monitoring of the Redis server
 | 
				
			||||||
 | 
					# and persistence, you may want to disable this feature so that Redis will
 | 
				
			||||||
 | 
					# continue to work as usual even if there are problems with disk,
 | 
				
			||||||
 | 
					# permissions, and so forth.
 | 
				
			||||||
 | 
					stop-writes-on-bgsave-error yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Compress string objects using LZF when dump .rdb databases?
 | 
					# Compress string objects using LZF when dump .rdb databases?
 | 
				
			||||||
# For default that's set to 'yes' as it's almost always a win.
 | 
					# For default that's set to 'yes' as it's almost always a win.
 | 
				
			||||||
@@ -93,6 +155,15 @@ databases 16
 | 
				
			|||||||
# the dataset will likely be bigger if you have compressible values or keys.
 | 
					# the dataset will likely be bigger if you have compressible values or keys.
 | 
				
			||||||
rdbcompression yes
 | 
					rdbcompression yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
 | 
				
			||||||
 | 
					# This makes the format more resistant to corruption but there is a performance
 | 
				
			||||||
 | 
					# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
 | 
				
			||||||
 | 
					# for maximum performances.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# RDB files created with checksum disabled have a checksum of zero that will
 | 
				
			||||||
 | 
					# tell the loading code to skip the check.
 | 
				
			||||||
 | 
					rdbchecksum yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The filename where to dump the DB
 | 
					# The filename where to dump the DB
 | 
				
			||||||
dbfilename dump.rdb
 | 
					dbfilename dump.rdb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,7 +172,7 @@ dbfilename dump.rdb
 | 
				
			|||||||
# The DB will be written inside this directory, with the filename specified
 | 
					# The DB will be written inside this directory, with the filename specified
 | 
				
			||||||
# above using the 'dbfilename' configuration directive.
 | 
					# above using the 'dbfilename' configuration directive.
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# Also the Append Only File will be created inside this directory.
 | 
					# The Append Only File will also be created inside this directory.
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# Note that you must specify a directory here, not a file name.
 | 
					# Note that you must specify a directory here, not a file name.
 | 
				
			||||||
dir /var/lib/redis
 | 
					dir /var/lib/redis
 | 
				
			||||||
@@ -122,27 +193,46 @@ dir /var/lib/redis
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# masterauth <master-password>
 | 
					# masterauth <master-password>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# When a slave lost the connection with the master, or when the replication
 | 
					# When a slave loses its connection with the master, or when the replication
 | 
				
			||||||
# is still in progress, the slave can act in two different ways:
 | 
					# is still in progress, the slave can act in two different ways:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
 | 
					# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will
 | 
				
			||||||
#    still reply to client requests, possibly with out of data data, or the
 | 
					#    still reply to client requests, possibly with out of date data, or the
 | 
				
			||||||
#    data set may just be empty if this is the first synchronization.
 | 
					#    data set may just be empty if this is the first synchronization.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# 2) if slave-serve-stale data is set to 'no' the slave will reply with
 | 
					# 2) if slave-serve-stale-data is set to 'no' the slave will reply with
 | 
				
			||||||
#    an error "SYNC with master in progress" to all the kind of commands
 | 
					#    an error "SYNC with master in progress" to all the kind of commands
 | 
				
			||||||
#    but to INFO and SLAVEOF.
 | 
					#    but to INFO and SLAVEOF.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
slave-serve-stale-data yes
 | 
					slave-serve-stale-data yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# You can configure a slave instance to accept writes or not. Writing against
 | 
				
			||||||
 | 
					# a slave instance may be useful to store some ephemeral data (because data
 | 
				
			||||||
 | 
					# written on a slave will be easily deleted after resync with the master) but
 | 
				
			||||||
 | 
					# may also cause problems if clients are writing to it because of a
 | 
				
			||||||
 | 
					# misconfiguration.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Since Redis 2.6 by default slaves are read-only.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Note: read only slaves are not designed to be exposed to untrusted clients
 | 
				
			||||||
 | 
					# on the internet. It's just a protection layer against misuse of the instance.
 | 
				
			||||||
 | 
					# Still a read only slave exports by default all the administrative commands
 | 
				
			||||||
 | 
					# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve
 | 
				
			||||||
 | 
					# security of read only slaves using 'rename-command' to shadow all the
 | 
				
			||||||
 | 
					# administrative / dangerous commands.
 | 
				
			||||||
 | 
					slave-read-only yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Slaves send PINGs to server in a predefined interval. It's possible to change
 | 
					# Slaves send PINGs to server in a predefined interval. It's possible to change
 | 
				
			||||||
# this interval with the repl_ping_slave_period option. The default value is 10
 | 
					# this interval with the repl_ping_slave_period option. The default value is 10
 | 
				
			||||||
# seconds.
 | 
					# seconds.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# repl-ping-slave-period 10
 | 
					# repl-ping-slave-period 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The following option sets a timeout for both Bulk transfer I/O timeout and
 | 
					# The following option sets the replication timeout for:
 | 
				
			||||||
# master data or ping response timeout. The default value is 60 seconds.
 | 
					#
 | 
				
			||||||
 | 
					# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
 | 
				
			||||||
 | 
					# 2) Master timeout from the point of view of slaves (data, pings).
 | 
				
			||||||
 | 
					# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It is important to make sure that this value is greater than the value
 | 
					# It is important to make sure that this value is greater than the value
 | 
				
			||||||
# specified for repl-ping-slave-period otherwise a timeout will be detected
 | 
					# specified for repl-ping-slave-period otherwise a timeout will be detected
 | 
				
			||||||
@@ -150,6 +240,80 @@ slave-serve-stale-data yes
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# repl-timeout 60
 | 
					# repl-timeout 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Disable TCP_NODELAY on the slave socket after SYNC?
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If you select "yes" Redis will use a smaller number of TCP packets and
 | 
				
			||||||
 | 
					# less bandwidth to send data to slaves. But this can add a delay for
 | 
				
			||||||
 | 
					# the data to appear on the slave side, up to 40 milliseconds with
 | 
				
			||||||
 | 
					# Linux kernels using a default configuration.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If you select "no" the delay for data to appear on the slave side will
 | 
				
			||||||
 | 
					# be reduced but more bandwidth will be used for replication.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# By default we optimize for low latency, but in very high traffic conditions
 | 
				
			||||||
 | 
					# or when the master and slaves are many hops away, turning this to "yes" may
 | 
				
			||||||
 | 
					# be a good idea.
 | 
				
			||||||
 | 
					repl-disable-tcp-nodelay no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set the replication backlog size. The backlog is a buffer that accumulates
 | 
				
			||||||
 | 
					# slave data when slaves are disconnected for some time, so that when a slave
 | 
				
			||||||
 | 
					# wants to reconnect again, often a full resync is not needed, but a partial
 | 
				
			||||||
 | 
					# resync is enough, just passing the portion of data the slave missed while
 | 
				
			||||||
 | 
					# disconnected.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The biggest the replication backlog, the longer the time the slave can be
 | 
				
			||||||
 | 
					# disconnected and later be able to perform a partial resynchronization.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The backlog is only allocated once there is at least a slave connected.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# repl-backlog-size 1mb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# After a master has no longer connected slaves for some time, the backlog
 | 
				
			||||||
 | 
					# will be freed. The following option configures the amount of seconds that
 | 
				
			||||||
 | 
					# need to elapse, starting from the time the last slave disconnected, for
 | 
				
			||||||
 | 
					# the backlog buffer to be freed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# A value of 0 means to never release the backlog.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# repl-backlog-ttl 3600
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The slave priority is an integer number published by Redis in the INFO output.
 | 
				
			||||||
 | 
					# It is used by Redis Sentinel in order to select a slave to promote into a
 | 
				
			||||||
 | 
					# master if the master is no longer working correctly.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# A slave with a low priority number is considered better for promotion, so
 | 
				
			||||||
 | 
					# for instance if there are three slaves with priority 10, 100, 25 Sentinel will
 | 
				
			||||||
 | 
					# pick the one with priority 10, that is the lowest.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# However a special priority of 0 marks the slave as not able to perform the
 | 
				
			||||||
 | 
					# role of master, so a slave with priority of 0 will never be selected by
 | 
				
			||||||
 | 
					# Redis Sentinel for promotion.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# By default the priority is 100.
 | 
				
			||||||
 | 
					slave-priority 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# It is possible for a master to stop accepting writes if there are less than
 | 
				
			||||||
 | 
					# N slaves connected, having a lag less or equal than M seconds.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The N slaves need to be in "online" state.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The lag in seconds, that must be <= the specified value, is calculated from
 | 
				
			||||||
 | 
					# the last ping received from the slave, that is usually sent every second.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This option does not GUARANTEES that N replicas will accept the write, but
 | 
				
			||||||
 | 
					# will limit the window of exposure for lost writes in case not enough slaves
 | 
				
			||||||
 | 
					# are available, to the specified number of seconds.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# For example to require at least 3 slaves with a lag <= 10 seconds use:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# min-slaves-to-write 3
 | 
				
			||||||
 | 
					# min-slaves-max-lag 10
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Setting one or the other to 0 disables the feature.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# By default min-slaves-to-write is set to 0 (feature disabled) and
 | 
				
			||||||
 | 
					# min-slaves-max-lag is set to 10.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################## SECURITY ###################################
 | 
					################################## SECURITY ###################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Require clients to issue AUTH <PASSWORD> before processing any other
 | 
					# Require clients to issue AUTH <PASSWORD> before processing any other
 | 
				
			||||||
@@ -167,33 +331,39 @@ slave-serve-stale-data yes
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Command renaming.
 | 
					# Command renaming.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It is possilbe to change the name of dangerous commands in a shared
 | 
					# It is possible to change the name of dangerous commands in a shared
 | 
				
			||||||
# environment. For instance the CONFIG command may be renamed into something
 | 
					# environment. For instance the CONFIG command may be renamed into something
 | 
				
			||||||
# of hard to guess so that it will be still available for internal-use
 | 
					# hard to guess so that it will still be available for internal-use tools
 | 
				
			||||||
# tools but not available for general clients.
 | 
					# but not available for general clients.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Example:
 | 
					# Example:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
 | 
					# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It is also possilbe to completely kill a command renaming it into
 | 
					# It is also possible to completely kill a command by renaming it into
 | 
				
			||||||
# an empty string:
 | 
					# an empty string:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# rename-command CONFIG ""
 | 
					# rename-command CONFIG ""
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please note that changing the name of commands that are logged into the
 | 
				
			||||||
 | 
					# AOF file or transmitted to slaves may cause problems.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################### LIMITS ####################################
 | 
					################################### LIMITS ####################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Set the max number of connected clients at the same time. By default there
 | 
					# Set the max number of connected clients at the same time. By default
 | 
				
			||||||
# is no limit, and it's up to the number of file descriptors the Redis process
 | 
					# this limit is set to 10000 clients, however if the Redis server is not
 | 
				
			||||||
# is able to open. The special value '0' means no limits.
 | 
					# able to configure the process file limit to allow for the specified limit
 | 
				
			||||||
 | 
					# the max number of allowed clients is set to the current file limit
 | 
				
			||||||
 | 
					# minus 32 (as Redis reserves a few file descriptors for internal uses).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
# Once the limit is reached Redis will close all the new connections sending
 | 
					# Once the limit is reached Redis will close all the new connections sending
 | 
				
			||||||
# an error 'max number of clients reached'.
 | 
					# an error 'max number of clients reached'.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# maxclients 128
 | 
					# maxclients 10000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Don't use more memory than the specified amount of bytes.
 | 
					# Don't use more memory than the specified amount of bytes.
 | 
				
			||||||
# When the memory limit is reached Redis will try to remove keys
 | 
					# When the memory limit is reached Redis will try to remove keys
 | 
				
			||||||
# accordingly to the eviction policy selected (see maxmemmory-policy).
 | 
					# according to the eviction policy selected (see maxmemory-policy).
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# If Redis can't remove keys according to the policy, or if the policy is
 | 
					# If Redis can't remove keys according to the policy, or if the policy is
 | 
				
			||||||
# set to 'noeviction', Redis will start to reply with errors to commands
 | 
					# set to 'noeviction', Redis will start to reply with errors to commands
 | 
				
			||||||
@@ -201,7 +371,7 @@ slave-serve-stale-data yes
 | 
				
			|||||||
# to reply to read-only commands like GET.
 | 
					# to reply to read-only commands like GET.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This option is usually useful when using Redis as an LRU cache, or to set
 | 
					# This option is usually useful when using Redis as an LRU cache, or to set
 | 
				
			||||||
# an hard memory limit for an instance (using the 'noeviction' policy).
 | 
					# a hard memory limit for an instance (using the 'noeviction' policy).
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# WARNING: If you have slaves attached to an instance with maxmemory on,
 | 
					# WARNING: If you have slaves attached to an instance with maxmemory on,
 | 
				
			||||||
# the size of the output buffers needed to feed the slaves are subtracted
 | 
					# the size of the output buffers needed to feed the slaves are subtracted
 | 
				
			||||||
@@ -217,16 +387,16 @@ slave-serve-stale-data yes
 | 
				
			|||||||
# maxmemory <bytes>
 | 
					# maxmemory <bytes>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
 | 
					# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
 | 
				
			||||||
# is reached? You can select among five behavior:
 | 
					# is reached. You can select among five behaviors:
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# volatile-lru -> remove the key with an expire set using an LRU algorithm
 | 
					# volatile-lru -> remove the key with an expire set using an LRU algorithm
 | 
				
			||||||
# allkeys-lru -> remove any key accordingly to the LRU algorithm
 | 
					# allkeys-lru -> remove any key accordingly to the LRU algorithm
 | 
				
			||||||
# volatile-random -> remove a random key with an expire set
 | 
					# volatile-random -> remove a random key with an expire set
 | 
				
			||||||
# allkeys->random -> remove a random key, any key
 | 
					# allkeys-random -> remove a random key, any key
 | 
				
			||||||
# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
 | 
					# volatile-ttl -> remove the key with the nearest expire time (minor TTL)
 | 
				
			||||||
# noeviction -> don't expire at all, just return an error on write operations
 | 
					# noeviction -> don't expire at all, just return an error on write operations
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# Note: with all the kind of policies, Redis will return an error on write
 | 
					# Note: with any of the above policies, Redis will return an error on write
 | 
				
			||||||
#       operations, when there are not suitable keys for eviction.
 | 
					#       operations, when there are not suitable keys for eviction.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
#       At the date of writing this commands are: set setnx setex append
 | 
					#       At the date of writing this commands are: set setnx setex append
 | 
				
			||||||
@@ -249,26 +419,29 @@ slave-serve-stale-data yes
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
############################## APPEND ONLY MODE ###############################
 | 
					############################## APPEND ONLY MODE ###############################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# By default Redis asynchronously dumps the dataset on disk. If you can live
 | 
					# By default Redis asynchronously dumps the dataset on disk. This mode is
 | 
				
			||||||
# with the idea that the latest records will be lost if something like a crash
 | 
					# good enough in many applications, but an issue with the Redis process or
 | 
				
			||||||
# happens this is the preferred way to run Redis. If instead you care a lot
 | 
					# a power outage may result into a few minutes of writes lost (depending on
 | 
				
			||||||
# about your data and don't want to that a single record can get lost you should
 | 
					# the configured save points).
 | 
				
			||||||
# enable the append only mode: when this mode is enabled Redis will append
 | 
					 | 
				
			||||||
# every write operation received in the file appendonly.aof. This file will
 | 
					 | 
				
			||||||
# be read on startup in order to rebuild the full dataset in memory.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Note that you can have both the async dumps and the append only file if you
 | 
					# The Append Only File is an alternative persistence mode that provides
 | 
				
			||||||
# like (you have to comment the "save" statements above to disable the dumps).
 | 
					# much better durability. For instance using the default data fsync policy
 | 
				
			||||||
# Still if append only mode is enabled Redis will load the data from the
 | 
					# (see later in the config file) Redis can lose just one second of writes in a
 | 
				
			||||||
# log file at startup ignoring the dump.rdb file.
 | 
					# dramatic event like a server power outage, or a single write if something
 | 
				
			||||||
 | 
					# wrong with the Redis process itself happens, but the operating system is
 | 
				
			||||||
 | 
					# still running correctly.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
 | 
					# AOF and RDB persistence can be enabled at the same time without problems.
 | 
				
			||||||
# log file in background when it gets too big.
 | 
					# If the AOF is enabled on startup Redis will load the AOF, that is the file
 | 
				
			||||||
 | 
					# with the better durability guarantees.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Please check http://redis.io/topics/persistence for more information.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
appendonly no
 | 
					appendonly no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The name of the append only file (default: "appendonly.aof")
 | 
					# The name of the append only file (default: "appendonly.aof")
 | 
				
			||||||
# appendfilename appendonly.aof
 | 
					
 | 
				
			||||||
 | 
					appendfilename "appendonly.aof"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The fsync() call tells the Operating System to actually write data on disk
 | 
					# The fsync() call tells the Operating System to actually write data on disk
 | 
				
			||||||
# instead to wait for more data in the output buffer. Some OS will really flush 
 | 
					# instead to wait for more data in the output buffer. Some OS will really flush 
 | 
				
			||||||
@@ -278,16 +451,19 @@ appendonly no
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# no: don't fsync, just let the OS flush the data when it wants. Faster.
 | 
					# no: don't fsync, just let the OS flush the data when it wants. Faster.
 | 
				
			||||||
# always: fsync after every write to the append only log . Slow, Safest.
 | 
					# always: fsync after every write to the append only log . Slow, Safest.
 | 
				
			||||||
# everysec: fsync only if one second passed since the last fsync. Compromise.
 | 
					# everysec: fsync only one time every second. Compromise.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The default is "everysec" that's usually the right compromise between
 | 
					# The default is "everysec", as that's usually the right compromise between
 | 
				
			||||||
# speed and data safety. It's up to you to understand if you can relax this to
 | 
					# speed and data safety. It's up to you to understand if you can relax this to
 | 
				
			||||||
# "no" that will will let the operating system flush the output buffer when
 | 
					# "no" that will let the operating system flush the output buffer when
 | 
				
			||||||
# it wants, for better performances (but if you can live with the idea of
 | 
					# it wants, for better performances (but if you can live with the idea of
 | 
				
			||||||
# some data loss consider the default persistence mode that's snapshotting),
 | 
					# some data loss consider the default persistence mode that's snapshotting),
 | 
				
			||||||
# or on the contrary, use "always" that's very slow but a bit safer than
 | 
					# or on the contrary, use "always" that's very slow but a bit safer than
 | 
				
			||||||
# everysec.
 | 
					# everysec.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					# More details please check the following article:
 | 
				
			||||||
 | 
					# http://antirez.com/post/redis-persistence-demystified.html
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
# If unsure, use "everysec".
 | 
					# If unsure, use "everysec".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# appendfsync always
 | 
					# appendfsync always
 | 
				
			||||||
@@ -305,21 +481,22 @@ appendfsync everysec
 | 
				
			|||||||
# that will prevent fsync() from being called in the main process while a
 | 
					# that will prevent fsync() from being called in the main process while a
 | 
				
			||||||
# BGSAVE or BGREWRITEAOF is in progress.
 | 
					# BGSAVE or BGREWRITEAOF is in progress.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This means that while another child is saving the durability of Redis is
 | 
					# This means that while another child is saving, the durability of Redis is
 | 
				
			||||||
# the same as "appendfsync none", that in pratical terms means that it is
 | 
					# the same as "appendfsync none". In practical terms, this means that it is
 | 
				
			||||||
# possible to lost up to 30 seconds of log in the worst scenario (with the
 | 
					# possible to lose up to 30 seconds of log in the worst scenario (with the
 | 
				
			||||||
# default Linux settings).
 | 
					# default Linux settings).
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# If you have latency problems turn this to "yes". Otherwise leave it as
 | 
					# If you have latency problems turn this to "yes". Otherwise leave it as
 | 
				
			||||||
# "no" that is the safest pick from the point of view of durability.
 | 
					# "no" that is the safest pick from the point of view of durability.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
no-appendfsync-on-rewrite no
 | 
					no-appendfsync-on-rewrite no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Automatic rewrite of the append only file.
 | 
					# Automatic rewrite of the append only file.
 | 
				
			||||||
# Redis is able to automatically rewrite the log file implicitly calling
 | 
					# Redis is able to automatically rewrite the log file implicitly calling
 | 
				
			||||||
# BGREWRITEAOF when the AOF log size will growth by the specified percentage.
 | 
					# BGREWRITEAOF when the AOF log size grows by the specified percentage.
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# This is how it works: Redis remembers the size of the AOF file after the
 | 
					# This is how it works: Redis remembers the size of the AOF file after the
 | 
				
			||||||
# latest rewrite (or if no rewrite happened since the restart, the size of
 | 
					# latest rewrite (if no rewrite has happened since the restart, the size of
 | 
				
			||||||
# the AOF at startup is used).
 | 
					# the AOF at startup is used).
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This base size is compared to the current size. If the current size is
 | 
					# This base size is compared to the current size. If the current size is
 | 
				
			||||||
@@ -328,12 +505,30 @@ no-appendfsync-on-rewrite no
 | 
				
			|||||||
# is useful to avoid rewriting the AOF file even if the percentage increase
 | 
					# is useful to avoid rewriting the AOF file even if the percentage increase
 | 
				
			||||||
# is reached but it is still pretty small.
 | 
					# is reached but it is still pretty small.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Specify a precentage of zero in order to disable the automatic AOF
 | 
					# Specify a percentage of zero in order to disable the automatic AOF
 | 
				
			||||||
# rewrite feature.
 | 
					# rewrite feature.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
auto-aof-rewrite-percentage 100
 | 
					auto-aof-rewrite-percentage 100
 | 
				
			||||||
auto-aof-rewrite-min-size 64mb
 | 
					auto-aof-rewrite-min-size 64mb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					################################ LUA SCRIPTING  ###############################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Max execution time of a Lua script in milliseconds.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If the maximum execution time is reached Redis will log that a script is
 | 
				
			||||||
 | 
					# still in execution after the maximum allowed time and will start to
 | 
				
			||||||
 | 
					# reply to queries with an error.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# When a long running script exceed the maximum execution time only the
 | 
				
			||||||
 | 
					# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be
 | 
				
			||||||
 | 
					# used to stop a script that did not yet called write commands. The second
 | 
				
			||||||
 | 
					# is the only way to shut down the server in the case a write commands was
 | 
				
			||||||
 | 
					# already issue by the script but the user don't want to wait for the natural
 | 
				
			||||||
 | 
					# termination of the script.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Set it to 0 or a negative value for unlimited execution without warnings.
 | 
				
			||||||
 | 
					lua-time-limit 5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################## SLOW LOG ###################################
 | 
					################################## SLOW LOG ###################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The Redis Slow Log is a system to log queries that exceeded a specified
 | 
					# The Redis Slow Log is a system to log queries that exceeded a specified
 | 
				
			||||||
@@ -358,88 +553,59 @@ slowlog-log-slower-than 10000
 | 
				
			|||||||
# You can reclaim memory used by the slow log with SLOWLOG RESET.
 | 
					# You can reclaim memory used by the slow log with SLOWLOG RESET.
 | 
				
			||||||
slowlog-max-len 128
 | 
					slowlog-max-len 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################ VIRTUAL MEMORY ###############################
 | 
					############################# Event notification ##############################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### WARNING! Virtual Memory is deprecated in Redis 2.4
 | 
					# Redis can notify Pub/Sub clients about events happening in the key space.
 | 
				
			||||||
### The use of Virtual Memory is strongly discouraged.
 | 
					# This feature is documented at http://redis.io/topics/keyspace-events
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Virtual Memory allows Redis to work with datasets bigger than the actual
 | 
					 | 
				
			||||||
# amount of RAM needed to hold the whole dataset in memory.
 | 
					 | 
				
			||||||
# In order to do so very used keys are taken in memory while the other keys
 | 
					 | 
				
			||||||
# are swapped into a swap file, similarly to what operating systems do
 | 
					 | 
				
			||||||
# with memory pages.
 | 
					 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
# To enable VM just set 'vm-enabled' to yes, and set the following three
 | 
					# For instance if keyspace events notification is enabled, and a client
 | 
				
			||||||
# VM parameters accordingly to your needs.
 | 
					# performs a DEL operation on key "foo" stored in the Database 0, two
 | 
				
			||||||
 | 
					# messages will be published via Pub/Sub:
 | 
				
			||||||
vm-enabled no
 | 
					 | 
				
			||||||
# vm-enabled yes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This is the path of the Redis swap file. As you can guess, swap files
 | 
					 | 
				
			||||||
# can't be shared by different Redis instances, so make sure to use a swap
 | 
					 | 
				
			||||||
# file for every redis process you are running. Redis will complain if the
 | 
					 | 
				
			||||||
# swap file is already in use.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The best kind of storage for the Redis swap file (that's accessed at random)
 | 
					# PUBLISH __keyspace@0__:foo del
 | 
				
			||||||
# is a Solid State Disk (SSD).
 | 
					# PUBLISH __keyevent@0__:del foo
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# *** WARNING *** if you are using a shared hosting the default of putting
 | 
					# It is possible to select the events that Redis will notify among a set
 | 
				
			||||||
# the swap file under /tmp is not secure. Create a dir with access granted
 | 
					# of classes. Every class is identified by a single character:
 | 
				
			||||||
# only to Redis user and configure Redis to create the swap file there.
 | 
					 | 
				
			||||||
vm-swap-file /var/lib/redis/redis.swap
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# vm-max-memory configures the VM to use at max the specified amount of
 | 
					 | 
				
			||||||
# RAM. Everything that deos not fit will be swapped on disk *if* possible, that
 | 
					 | 
				
			||||||
# is, if there is still enough contiguous space in the swap file.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# With vm-max-memory 0 the system will swap everything it can. Not a good
 | 
					#  K     Keyspace events, published with __keyspace@<db>__ prefix.
 | 
				
			||||||
# default, just specify the max amount of RAM you can in bytes, but it's
 | 
					#  E     Keyevent events, published with __keyevent@<db>__ prefix.
 | 
				
			||||||
# better to leave some margin. For instance specify an amount of RAM
 | 
					#  g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
 | 
				
			||||||
# that's more or less between 60 and 80% of your free RAM.
 | 
					#  $     String commands
 | 
				
			||||||
vm-max-memory 0
 | 
					#  l     List commands
 | 
				
			||||||
 | 
					#  s     Set commands
 | 
				
			||||||
# Redis swap files is split into pages. An object can be saved using multiple
 | 
					#  h     Hash commands
 | 
				
			||||||
# contiguous pages, but pages can't be shared between different objects.
 | 
					#  z     Sorted set commands
 | 
				
			||||||
# So if your page is too big, small objects swapped out on disk will waste
 | 
					#  x     Expired events (events generated every time a key expires)
 | 
				
			||||||
# a lot of space. If you page is too small, there is less space in the swap
 | 
					#  e     Evicted events (events generated when a key is evicted for maxmemory)
 | 
				
			||||||
# file (assuming you configured the same number of total swap file pages).
 | 
					#  A     Alias for g$lshzxe, so that the "AKE" string means all the events.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# If you use a lot of small objects, use a page size of 64 or 32 bytes.
 | 
					#  The "notify-keyspace-events" takes as argument a string that is composed
 | 
				
			||||||
# If you use a lot of big objects, use a bigger page size.
 | 
					#  by zero or multiple characters. The empty string means that notifications
 | 
				
			||||||
# If unsure, use the default :)
 | 
					#  are disabled at all.
 | 
				
			||||||
vm-page-size 32
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Number of total memory pages in the swap file.
 | 
					 | 
				
			||||||
# Given that the page table (a bitmap of free/used pages) is taken in memory,
 | 
					 | 
				
			||||||
# every 8 pages on disk will consume 1 byte of RAM.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The total swap size is vm-page-size * vm-pages
 | 
					#  Example: to enable list and generic events, from the point of view of the
 | 
				
			||||||
 | 
					#           event name, use:
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# With the default of 32-bytes memory pages and 134217728 pages Redis will
 | 
					#  notify-keyspace-events Elg
 | 
				
			||||||
# use a 4 GB swap file, that will use 16 MB of RAM for the page table.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# It's better to use the smallest acceptable value for your application,
 | 
					#  Example 2: to get the stream of the expired keys subscribing to channel
 | 
				
			||||||
# but the default is large in order to work in most conditions.
 | 
					#             name __keyevent@0__:expired use:
 | 
				
			||||||
vm-pages 134217728
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Max number of VM I/O threads running at the same time.
 | 
					 | 
				
			||||||
# This threads are used to read/write data from/to swap file, since they
 | 
					 | 
				
			||||||
# also encode and decode objects from disk to memory or the reverse, a bigger
 | 
					 | 
				
			||||||
# number of threads can help with big objects even if they can't help with
 | 
					 | 
				
			||||||
# I/O itself as the physical device may not be able to couple with many
 | 
					 | 
				
			||||||
# reads/writes operations at the same time.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# The special value of 0 turn off threaded I/O and enables the blocking
 | 
					#  notify-keyspace-events Ex
 | 
				
			||||||
# Virtual Memory implementation.
 | 
					#
 | 
				
			||||||
vm-max-threads 4
 | 
					#  By default all notifications are disabled because most users don't need
 | 
				
			||||||
 | 
					#  this feature and the feature has some overhead. Note that if you don't
 | 
				
			||||||
 | 
					#  specify at least one of K or E, no events will be delivered.
 | 
				
			||||||
 | 
					notify-keyspace-events ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
############################### ADVANCED CONFIG ###############################
 | 
					############################### ADVANCED CONFIG ###############################
 | 
				
			||||||
# Hashes are encoded in a special way (much more memory efficient) when they
 | 
					
 | 
				
			||||||
# have at max a given numer of elements, and the biggest element does not
 | 
					# Hashes are encoded using a memory efficient data structure when they have a
 | 
				
			||||||
# exceed a given threshold. You can configure this limits with the following
 | 
					# small number of entries, and the biggest entry does not exceed a given
 | 
				
			||||||
# configuration directives.
 | 
					# threshold. These thresholds can be configured using the following directives.
 | 
				
			||||||
hash-max-zipmap-entries 512
 | 
					hash-max-ziplist-entries 512
 | 
				
			||||||
hash-max-zipmap-value 64
 | 
					hash-max-ziplist-value 64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Similarly to hashes, small lists are also encoded in a special way in order
 | 
					# Similarly to hashes, small lists are also encoded in a special way in order
 | 
				
			||||||
# to save a lot of space. The special representation is only used when
 | 
					# to save a lot of space. The special representation is only used when
 | 
				
			||||||
@@ -462,9 +628,9 @@ zset-max-ziplist-value 64
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
 | 
					# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in
 | 
				
			||||||
# order to help rehashing the main Redis hash table (the one mapping top-level
 | 
					# order to help rehashing the main Redis hash table (the one mapping top-level
 | 
				
			||||||
# keys to values). The hash table implementation redis uses (see dict.c)
 | 
					# keys to values). The hash table implementation Redis uses (see dict.c)
 | 
				
			||||||
# performs a lazy rehashing: the more operation you run into an hash table
 | 
					# performs a lazy rehashing: the more operation you run into a hash table
 | 
				
			||||||
# that is rhashing, the more rehashing "steps" are performed, so if the
 | 
					# that is rehashing, the more rehashing "steps" are performed, so if the
 | 
				
			||||||
# server is idle the rehashing is never complete and some more memory is used
 | 
					# server is idle the rehashing is never complete and some more memory is used
 | 
				
			||||||
# by the hash table.
 | 
					# by the hash table.
 | 
				
			||||||
# 
 | 
					# 
 | 
				
			||||||
@@ -480,12 +646,65 @@ zset-max-ziplist-value 64
 | 
				
			|||||||
# want to free memory asap when possible.
 | 
					# want to free memory asap when possible.
 | 
				
			||||||
activerehashing yes
 | 
					activerehashing yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################## INCLUDES ###################################
 | 
					# The client output buffer limits can be used to force disconnection of clients
 | 
				
			||||||
 | 
					# that are not reading data from the server fast enough for some reason (a
 | 
				
			||||||
# Include one or more other config files here.  This is useful if you
 | 
					# common reason is that a Pub/Sub client can't consume messages as fast as the
 | 
				
			||||||
# have a standard template that goes to all redis server but also need
 | 
					# publisher can produce them).
 | 
				
			||||||
# to customize a few per-server settings.  Include files can include
 | 
					 | 
				
			||||||
# other files, so use this wisely.
 | 
					 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# include /path/to/local.conf
 | 
					# The limit can be set differently for the three different classes of clients:
 | 
				
			||||||
# include /path/to/other.conf
 | 
					#
 | 
				
			||||||
 | 
					# normal -> normal clients
 | 
				
			||||||
 | 
					# slave  -> slave clients and MONITOR clients
 | 
				
			||||||
 | 
					# pubsub -> clients subscribed to at least one pubsub channel or pattern
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The syntax of every client-output-buffer-limit directive is the following:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# A client is immediately disconnected once the hard limit is reached, or if
 | 
				
			||||||
 | 
					# the soft limit is reached and remains reached for the specified number of
 | 
				
			||||||
 | 
					# seconds (continuously).
 | 
				
			||||||
 | 
					# So for instance if the hard limit is 32 megabytes and the soft limit is
 | 
				
			||||||
 | 
					# 16 megabytes / 10 seconds, the client will get disconnected immediately
 | 
				
			||||||
 | 
					# if the size of the output buffers reach 32 megabytes, but will also get
 | 
				
			||||||
 | 
					# disconnected if the client reaches 16 megabytes and continuously overcomes
 | 
				
			||||||
 | 
					# the limit for 10 seconds.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# By default normal clients are not limited because they don't receive data
 | 
				
			||||||
 | 
					# without asking (in a push way), but just after a request, so only
 | 
				
			||||||
 | 
					# asynchronous clients may create a scenario where data is requested faster
 | 
				
			||||||
 | 
					# than it can read.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Instead there is a default limit for pubsub and slave clients, since
 | 
				
			||||||
 | 
					# subscribers and slaves receive data in a push fashion.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Both the hard or the soft limit can be disabled by setting them to zero.
 | 
				
			||||||
 | 
					client-output-buffer-limit normal 0 0 0
 | 
				
			||||||
 | 
					client-output-buffer-limit slave 256mb 64mb 60
 | 
				
			||||||
 | 
					client-output-buffer-limit pubsub 32mb 8mb 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Redis calls an internal function to perform many background tasks, like
 | 
				
			||||||
 | 
					# closing connections of clients in timeout, purging expired keys that are
 | 
				
			||||||
 | 
					# never requested, and so forth.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Not all tasks are performed with the same frequency, but Redis checks for
 | 
				
			||||||
 | 
					# tasks to perform accordingly to the specified "hz" value.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# By default "hz" is set to 10. Raising the value will use more CPU when
 | 
				
			||||||
 | 
					# Redis is idle, but at the same time will make Redis more responsive when
 | 
				
			||||||
 | 
					# there are many keys expiring at the same time, and timeouts may be
 | 
				
			||||||
 | 
					# handled with more precision.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The range is between 1 and 500, however a value over 100 is usually not
 | 
				
			||||||
 | 
					# a good idea. Most users should use the default of 10 and raise this up to
 | 
				
			||||||
 | 
					# 100 only in environments where very low latency is required.
 | 
				
			||||||
 | 
					hz 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# When a child rewrites the AOF file, if the following option is enabled
 | 
				
			||||||
 | 
					# the file will be fsync-ed every 32 MB of data generated. This is useful
 | 
				
			||||||
 | 
					# in order to commit the file to the disk more incrementally and avoid
 | 
				
			||||||
 | 
					# big latency spikes.
 | 
				
			||||||
 | 
					aof-rewrite-incremental-fsync yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Zulip-specific configuration: disable saving to disk.
 | 
				
			||||||
 | 
					save ""
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,8 +26,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/django.log        ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/django.log        ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
;stdout_logfile_maxbytes=1MB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
;stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
 | 
					;stdout_capture_maxbytes=1MB   ; number of bytes in 'capturemode' (default 0)
 | 
				
			||||||
;stdout_events_enabled=false   ; emit events on stdout writes (default false)
 | 
					;stdout_events_enabled=false   ; emit events on stdout writes (default false)
 | 
				
			||||||
;stderr_logfile=/var/log/zulip/app.err        ; stderr log path, NONE for none; default AUTO
 | 
					;stderr_logfile=/var/log/zulip/app.err        ; stderr log path, NONE for none; default AUTO
 | 
				
			||||||
@@ -52,6 +52,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/tornado.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/tornado.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-user-activity]
 | 
					[program:zulip-events-user-activity]
 | 
				
			||||||
@@ -64,6 +66,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-user-activity.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-user-activity.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-user-activity-interval]
 | 
					[program:zulip-events-user-activity-interval]
 | 
				
			||||||
@@ -76,6 +80,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-user-activity-interval.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-user-activity-interval.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-user-presence]
 | 
					[program:zulip-events-user-presence]
 | 
				
			||||||
@@ -88,6 +94,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-user-presence.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-user-presence.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-signups]
 | 
					[program:zulip-events-signups]
 | 
				
			||||||
@@ -100,6 +108,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-signups.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-signups.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-confirmation-emails]
 | 
					[program:zulip-events-confirmation-emails]
 | 
				
			||||||
@@ -112,6 +122,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-confirmation-emails.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-confirmation-emails.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-missedmessage_reminders]
 | 
					[program:zulip-events-missedmessage_reminders]
 | 
				
			||||||
@@ -124,6 +136,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-missedmessage_reminders.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-missedmessage_reminders.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-missedmessage_mobile_notifications]
 | 
					[program:zulip-events-missedmessage_mobile_notifications]
 | 
				
			||||||
@@ -136,6 +150,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-missedmessage_mobile_notifications.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-missedmessage_mobile_notifications.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-slowqueries]
 | 
					[program:zulip-events-slowqueries]
 | 
				
			||||||
@@ -148,6 +164,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-slow_queries.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-slow_queries.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-message_sender]
 | 
					[program:zulip-events-message_sender]
 | 
				
			||||||
@@ -161,6 +179,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-message_sender.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-message_sender.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
numprocs=5
 | 
					numprocs=5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,6 +194,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-feedback_messages.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-feedback_messages.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-error_reports]
 | 
					[program:zulip-events-error_reports]
 | 
				
			||||||
@@ -186,6 +208,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-error_reports.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-error_reports.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-digest_emails]
 | 
					[program:zulip-events-digest_emails]
 | 
				
			||||||
@@ -198,6 +222,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-digest_emails.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-digest_emails.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-events-email_mirror]
 | 
					[program:zulip-events-email_mirror]
 | 
				
			||||||
@@ -210,6 +236,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-email_mirror.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-email_mirror.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[program:zulip-deliver-enqueued-emails]
 | 
					[program:zulip-deliver-enqueued-emails]
 | 
				
			||||||
@@ -222,6 +250,8 @@ stopwaitsecs=30                ; max num secs to wait b4 SIGKILL (default 10)
 | 
				
			|||||||
user=zulip                    ; setuid to this UNIX account to run the program
 | 
					user=zulip                    ; setuid to this UNIX account to run the program
 | 
				
			||||||
redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
					redirect_stderr=true           ; redirect proc stderr to stdout (default false)
 | 
				
			||||||
stdout_logfile=/var/log/zulip/events-deliver_enqueued_emails.log         ; stdout log path, NONE for none; default AUTO
 | 
					stdout_logfile=/var/log/zulip/events-deliver_enqueued_emails.log         ; stdout log path, NONE for none; default AUTO
 | 
				
			||||||
 | 
					stdout_logfile_maxbytes=1GB   ; max # logfile bytes b4 rotation (default 50MB)
 | 
				
			||||||
 | 
					stdout_logfile_backups=10     ; # of stdout logfile backups (default 10)
 | 
				
			||||||
directory=/home/zulip/deployments/current/
 | 
					directory=/home/zulip/deployments/current/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,6 @@ class zulip::app_frontend {
 | 
				
			|||||||
                    # Django dependencies
 | 
					                    # Django dependencies
 | 
				
			||||||
                    "python-django",
 | 
					                    "python-django",
 | 
				
			||||||
                    "python-django-guardian",
 | 
					                    "python-django-guardian",
 | 
				
			||||||
                    "python-django-auth-openid",
 | 
					 | 
				
			||||||
                    "python-django-south",
 | 
					 | 
				
			||||||
                    "python-django-pipeline",
 | 
					                    "python-django-pipeline",
 | 
				
			||||||
                    "python-django-bitfield",
 | 
					                    "python-django-bitfield",
 | 
				
			||||||
                    # Needed for mock objects in decorators
 | 
					                    # Needed for mock objects in decorators
 | 
				
			||||||
@@ -28,7 +26,7 @@ class zulip::app_frontend {
 | 
				
			|||||||
                    # Used for Hesiod lookups, etc.
 | 
					                    # Used for Hesiod lookups, etc.
 | 
				
			||||||
                    "python-dns",
 | 
					                    "python-dns",
 | 
				
			||||||
                    # Needed to access our database
 | 
					                    # Needed to access our database
 | 
				
			||||||
                    "postgresql-client-9.1",
 | 
					                    "postgresql-client-9.3",
 | 
				
			||||||
                    "python-psycopg2",
 | 
					                    "python-psycopg2",
 | 
				
			||||||
                    # Needed for building complex DB queries
 | 
					                    # Needed for building complex DB queries
 | 
				
			||||||
                    "python-sqlalchemy",
 | 
					                    "python-sqlalchemy",
 | 
				
			||||||
@@ -49,7 +47,6 @@ class zulip::app_frontend {
 | 
				
			|||||||
                    # Needed for S3 file uploads
 | 
					                    # Needed for S3 file uploads
 | 
				
			||||||
                    "python-boto",
 | 
					                    "python-boto",
 | 
				
			||||||
                    # Needed to send email
 | 
					                    # Needed to send email
 | 
				
			||||||
                    "python-postmonkey",
 | 
					 | 
				
			||||||
                    "python-mandrill",
 | 
					                    "python-mandrill",
 | 
				
			||||||
                    # Needed to generate diffs for edits
 | 
					                    # Needed to generate diffs for edits
 | 
				
			||||||
                    "python-diff-match-patch",
 | 
					                    "python-diff-match-patch",
 | 
				
			||||||
@@ -63,6 +60,8 @@ class zulip::app_frontend {
 | 
				
			|||||||
                    "python-django-auth-ldap",
 | 
					                    "python-django-auth-ldap",
 | 
				
			||||||
                    # Needed for Google Apps mobile auth
 | 
					                    # Needed for Google Apps mobile auth
 | 
				
			||||||
                    "python-googleapi",
 | 
					                    "python-googleapi",
 | 
				
			||||||
 | 
					                    # Needed for JWT-based auth
 | 
				
			||||||
 | 
					                    "python-pyjwt",
 | 
				
			||||||
                    ]
 | 
					                    ]
 | 
				
			||||||
  define safepackage ( $ensure = present ) {
 | 
					  define safepackage ( $ensure = present ) {
 | 
				
			||||||
    if !defined(Package[$title]) {
 | 
					    if !defined(Package[$title]) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,12 @@ class zulip::base {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  group { 'zulip':
 | 
					  group { 'zulip':
 | 
				
			||||||
    ensure     => present,
 | 
					    ensure     => present,
 | 
				
			||||||
    gid        => '1000',
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  user { 'zulip':
 | 
					  user { 'zulip':
 | 
				
			||||||
    ensure     => present,
 | 
					    ensure     => present,
 | 
				
			||||||
    uid        => '1000',
 | 
					 | 
				
			||||||
    gid        => '1000',
 | 
					 | 
				
			||||||
    require    => Group['zulip'],
 | 
					    require    => Group['zulip'],
 | 
				
			||||||
 | 
					    gid        => 'zulip',
 | 
				
			||||||
    shell      => '/bin/bash',
 | 
					    shell      => '/bin/bash',
 | 
				
			||||||
    home       => '/home/zulip',
 | 
					    home       => '/home/zulip',
 | 
				
			||||||
    managehome => true,
 | 
					    managehome => true,
 | 
				
			||||||
@@ -41,14 +40,6 @@ class zulip::base {
 | 
				
			|||||||
    group      => 'zulip',
 | 
					    group      => 'zulip',
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  file { '/etc/puppet/puppet.conf':
 | 
					 | 
				
			||||||
    ensure     => file,
 | 
					 | 
				
			||||||
    mode       => 640,
 | 
					 | 
				
			||||||
    owner      => "root",
 | 
					 | 
				
			||||||
    group      => "root",
 | 
					 | 
				
			||||||
    source     => 'puppet:///modules/zulip/puppet.conf',
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  file { '/etc/security/limits.conf':
 | 
					  file { '/etc/security/limits.conf':
 | 
				
			||||||
    ensure     => file,
 | 
					    ensure     => file,
 | 
				
			||||||
    mode       => 640,
 | 
					    mode       => 640,
 | 
				
			||||||
@@ -57,6 +48,13 @@ class zulip::base {
 | 
				
			|||||||
    source     => 'puppet:///modules/zulip/limits.conf',
 | 
					    source     => 'puppet:///modules/zulip/limits.conf',
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # This directory is written to by cron jobs for reading by Nagios
 | 
				
			||||||
 | 
					  file { '/var/lib/nagios_state/':
 | 
				
			||||||
 | 
					    ensure     => directory,
 | 
				
			||||||
 | 
					    group      => 'zulip',
 | 
				
			||||||
 | 
					    mode       => 774,
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  file { '/var/log/zulip':
 | 
					  file { '/var/log/zulip':
 | 
				
			||||||
    ensure => 'directory',
 | 
					    ensure => 'directory',
 | 
				
			||||||
    owner  => 'zulip',
 | 
					    owner  => 'zulip',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ class zulip::postfix_localmail {
 | 
				
			|||||||
    mode    => 0644,
 | 
					    mode    => 0644,
 | 
				
			||||||
    owner   => root,
 | 
					    owner   => root,
 | 
				
			||||||
    group   => root,
 | 
					    group   => root,
 | 
				
			||||||
    content => "@${fqdn}",
 | 
					    content => "${fqdn}",
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  file {'/etc/postfix/main.cf':
 | 
					  file {'/etc/postfix/main.cf':
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ class zulip::postgres_appdb {
 | 
				
			|||||||
  $appdb_packages = [# Needed to run process_fts_updates
 | 
					  $appdb_packages = [# Needed to run process_fts_updates
 | 
				
			||||||
                     "python-psycopg2",
 | 
					                     "python-psycopg2",
 | 
				
			||||||
                     # Needed for our full text search system
 | 
					                     # Needed for our full text search system
 | 
				
			||||||
                     "postgresql-9.1-tsearch-extras",
 | 
					                     "postgresql-9.3-tsearch-extras",
 | 
				
			||||||
                     ]
 | 
					                     ]
 | 
				
			||||||
  define safepackage ( $ensure = present ) {
 | 
					  define safepackage ( $ensure = present ) {
 | 
				
			||||||
    if !defined(Package[$title]) {
 | 
					    if !defined(Package[$title]) {
 | 
				
			||||||
@@ -37,16 +37,16 @@ class zulip::postgres_appdb {
 | 
				
			|||||||
    notify => Service[supervisor],
 | 
					    notify => Service[supervisor],
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  file { '/usr/share/postgresql/9.1/tsearch_data/en_us.dict':
 | 
					  file { '/usr/share/postgresql/9.3/tsearch_data/en_us.dict':
 | 
				
			||||||
    ensure => 'link',
 | 
					    ensure => 'link',
 | 
				
			||||||
    target => '/var/cache/postgresql/dicts/en_us.dict',
 | 
					    target => '/var/cache/postgresql/dicts/en_us.dict',
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  file { '/usr/share/postgresql/9.1/tsearch_data/en_us.affix':
 | 
					  file { '/usr/share/postgresql/9.3/tsearch_data/en_us.affix':
 | 
				
			||||||
    ensure => 'link',
 | 
					    ensure => 'link',
 | 
				
			||||||
    target => '/var/cache/postgresql/dicts/en_us.affix',
 | 
					    target => '/var/cache/postgresql/dicts/en_us.affix',
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  file { "/usr/share/postgresql/9.1/tsearch_data/zulip_english.stop":
 | 
					  file { "/usr/share/postgresql/9.3/tsearch_data/zulip_english.stop":
 | 
				
			||||||
    require => Package["postgresql-9.1"],
 | 
					    require => Package["postgresql-9.3"],
 | 
				
			||||||
    ensure => file,
 | 
					    ensure => file,
 | 
				
			||||||
    owner => "root",
 | 
					    owner => "root",
 | 
				
			||||||
    group => "root",
 | 
					    group => "root",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
class zulip::postgres_common {
 | 
					class zulip::postgres_common {
 | 
				
			||||||
  $postgres_packages = [# The database itself
 | 
					  $postgres_packages = [# The database itself
 | 
				
			||||||
                        "postgresql-9.1",
 | 
					                        "postgresql-9.3",
 | 
				
			||||||
                        # tools for database setup
 | 
					                        # tools for database setup
 | 
				
			||||||
                        "pgtune",
 | 
					                        "pgtune",
 | 
				
			||||||
                        # tools for database monitoring
 | 
					                        # tools for database monitoring
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,15 @@
 | 
				
			|||||||
class zulip::enterprise {
 | 
					class zulip::voyager {
 | 
				
			||||||
  include zulip::base
 | 
					  include zulip::base
 | 
				
			||||||
  include zulip::app_frontend
 | 
					  include zulip::app_frontend
 | 
				
			||||||
  include zulip::postgres_appdb
 | 
					  include zulip::postgres_appdb
 | 
				
			||||||
  include zulip::redis
 | 
					  include zulip::redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  apt::source {'zulip':
 | 
					  apt::source {'zulip':
 | 
				
			||||||
    location    => 'http://apt.zulip.com/enterprise',
 | 
					    location    => 'http://ppa.launchpad.net/tabbott/zulip/ubuntu',
 | 
				
			||||||
    release     => 'precise',
 | 
					    release     => 'trusty',
 | 
				
			||||||
    repos       => 'v1',
 | 
					    repos       => 'main',
 | 
				
			||||||
    key         => 'E5FB045CA79AA8FC25FDE9F3B4F81D07A529EF65',
 | 
					    key         => '84C2BE60E50E336456E4749CE84240474E26AE47',
 | 
				
			||||||
    key_source  => 'https://zulip.com/dist/keys/enterprise.asc',
 | 
					    key_source  => 'https://zulip.com/dist/keys/zulip.asc',
 | 
				
			||||||
    pin         => '995',
 | 
					    pin         => '995',
 | 
				
			||||||
    include_src => true,
 | 
					    include_src => true,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -44,8 +44,8 @@ class zulip::enterprise {
 | 
				
			|||||||
    source => "puppet:///modules/zulip/cron.d/restart-zulip",
 | 
					    source => "puppet:///modules/zulip/cron.d/restart-zulip",
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  file { '/etc/postgresql/9.1/main/postgresql.conf.template':
 | 
					  file { '/etc/postgresql/9.3/main/postgresql.conf.template':
 | 
				
			||||||
    require => Package["postgresql-9.1"],
 | 
					    require => Package["postgresql-9.3"],
 | 
				
			||||||
    ensure => file,
 | 
					    ensure => file,
 | 
				
			||||||
    owner  => "postgres",
 | 
					    owner  => "postgres",
 | 
				
			||||||
    group  => "postgres",
 | 
					    group  => "postgres",
 | 
				
			||||||
@@ -82,12 +82,12 @@ vm.dirty_background_ratio = 5
 | 
				
			|||||||
  exec { 'pgtune':
 | 
					  exec { 'pgtune':
 | 
				
			||||||
    require => Package["pgtune"],
 | 
					    require => Package["pgtune"],
 | 
				
			||||||
    # Let Postgres use half the memory on the machine
 | 
					    # Let Postgres use half the memory on the machine
 | 
				
			||||||
    command => "pgtune -T Web -M $half_memory -i /etc/postgresql/9.1/main/postgresql.conf.template -o /etc/postgresql/9.1/main/postgresql.conf",
 | 
					    command => "pgtune -T Web -M $half_memory -i /etc/postgresql/9.3/main/postgresql.conf.template -o /etc/postgresql/9.3/main/postgresql.conf",
 | 
				
			||||||
    refreshonly => true,
 | 
					    refreshonly => true,
 | 
				
			||||||
    subscribe => File['/etc/postgresql/9.1/main/postgresql.conf.template']
 | 
					    subscribe => File['/etc/postgresql/9.3/main/postgresql.conf.template']
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  exec { 'pg_ctlcluster 9.1 main restart':
 | 
					  exec { 'pg_ctlcluster 9.3 main restart':
 | 
				
			||||||
    require => Exec["sysctl_p"],
 | 
					    require => Exec["sysctl_p"],
 | 
				
			||||||
    refreshonly => true,
 | 
					    refreshonly => true,
 | 
				
			||||||
    subscribe => [ Exec['pgtune'], File['/etc/sysctl.d/40-postgresql.conf'] ]
 | 
					    subscribe => [ Exec['pgtune'], File['/etc/sysctl.d/40-postgresql.conf'] ]
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
# This file is managed by puppet; local changes will be overridden.
 | 
					# This file is managed by puppet; local changes will be overridden.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
smtpd_banner = $myhostname ESMTP $mail_name (Zulip Enterprise)
 | 
					smtpd_banner = $myhostname ESMTP $mail_name (Zulip Voyager)
 | 
				
			||||||
biff = no
 | 
					biff = no
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# appending .domain is the MUA's job.
 | 
					# appending .domain is the MUA's job.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,83 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIE+zCCA+OgAwIBAgIQDJOL1Hip5tpyq5kwwV/lQzANBgkqhkiG9w0BAQUFADBz
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
 | 
					 | 
				
			||||||
VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEZMBcGA1UE
 | 
					 | 
				
			||||||
AxMQUG9zaXRpdmVTU0wgQ0EgMjAeFw0xMzA3MTIwMDAwMDBaFw0xNDA3MTIyMzU5
 | 
					 | 
				
			||||||
NTlaMFExITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEUMBIGA1UE
 | 
					 | 
				
			||||||
CxMLUG9zaXRpdmVTU0wxFjAUBgNVBAMTDWFwaS56dWxpcC5jb20wggEiMA0GCSqG
 | 
					 | 
				
			||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+GsCaNbs6bR4CB0MJ2NARH0JMoXsCVHHC
 | 
					 | 
				
			||||||
fT149arpZoAf9s4cmUgqe/qXl7jeh1Hb5UtARhchNMR/poFX9Dd73qTVfDEvtASW
 | 
					 | 
				
			||||||
ezpsEAB3KJQiISjUyL8xxRAggYf5AXtJ2QzaHoQ3sQk65lVuarB4aQwFB+SsbdtU
 | 
					 | 
				
			||||||
dDTHAgnJ3p8Vz4cFjus2n/EW+td5c74V7Y6nAj/ww8ygRRdAvfGmHa84ZHEu+xCI
 | 
					 | 
				
			||||||
5cnX0704hJETDfv1ELg257Rmg5pbwHfThSGs5KWv7AQqpLg+wNRD/s5LO1o6zB1z
 | 
					 | 
				
			||||||
Toidcq8HaD2/hS3oAQUibySRjieTHE1JU1ueqjfn0grrCpoSjgrDAgMBAAGjggGr
 | 
					 | 
				
			||||||
MIIBpzAfBgNVHSMEGDAWgBSZ5EBfaxRePgXZ3dNjVPxiuPcArDAdBgNVHQ4EFgQU
 | 
					 | 
				
			||||||
py+lc7gytud0YnB4ddplmEgkEeIwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQC
 | 
					 | 
				
			||||||
MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFAGA1UdIARJMEcwOwYL
 | 
					 | 
				
			||||||
KwYBBAGyMQECAgcwLDAqBggrBgEFBQcCARYeaHR0cDovL3d3dy5wb3NpdGl2ZXNz
 | 
					 | 
				
			||||||
bC5jb20vQ1BTMAgGBmeBDAECATA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3Js
 | 
					 | 
				
			||||||
LmNvbW9kb2NhLmNvbS9Qb3NpdGl2ZVNTTENBMi5jcmwwbAYIKwYBBQUHAQEEYDBe
 | 
					 | 
				
			||||||
MDYGCCsGAQUFBzAChipodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9Qb3NpdGl2ZVNT
 | 
					 | 
				
			||||||
TENBMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAr
 | 
					 | 
				
			||||||
BgNVHREEJDAigg1hcGkuenVsaXAuY29tghF3d3cuYXBpLnp1bGlwLmNvbTANBgkq
 | 
					 | 
				
			||||||
hkiG9w0BAQUFAAOCAQEAQKpkB8eRq5K2KBMVFolxSqix4qWo/uPiOQU6kbjkJNdK
 | 
					 | 
				
			||||||
P1Wg+p1R1KsLTLDEZmqTnfIBluez/RqfEoPdh+cF2e0GP55Y2ogno+89oaW4ijUr
 | 
					 | 
				
			||||||
IgTor/b1ZVv+yQIi/u27hLpq/h5E5ZM6HpmQ5YcA4z3MY7VoXNxYY5iO34YzuD0n
 | 
					 | 
				
			||||||
emoDuM1JJuGTzPkxE/dUzRU7GUmi5cXQgdGQ9lvutI/DuyZsDJV54TW2882cpW82
 | 
					 | 
				
			||||||
5x4a77Esvx7VlqBC5KxN/NPN/ZwIs5vl4F1+/sf2Tr7oMDkZ4Tc944mkj5MAbhhm
 | 
					 | 
				
			||||||
JZV4K+MlPPP7VSWOr+y+lMHAAqk7nhBi8MPP4XOo0A==
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIE5TCCA82gAwIBAgIQB28SRoFFnCjVSNaXxA4AGzANBgkqhkiG9w0BAQUFADBv
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
 | 
					 | 
				
			||||||
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
 | 
					 | 
				
			||||||
eHRlcm5hbCBDQSBSb290MB4XDTEyMDIxNjAwMDAwMFoXDTIwMDUzMDEwNDgzOFow
 | 
					 | 
				
			||||||
czELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
 | 
					 | 
				
			||||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxGTAXBgNV
 | 
					 | 
				
			||||||
BAMTEFBvc2l0aXZlU1NMIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
 | 
					 | 
				
			||||||
AoIBAQDo6jnjIqaqucQA0OeqZztDB71Pkuu8vgGjQK3g70QotdA6voBUF4V6a4Rs
 | 
					 | 
				
			||||||
NjbloyTi/igBkLzX3Q+5K05IdwVpr95XMLHo+xoD9jxbUx6hAUlocnPWMytDqTcy
 | 
					 | 
				
			||||||
Ug+uJ1YxMGCtyb1zLDnukNh1sCUhYHsqfwL9goUfdE+SNHNcHQCgsMDqmOK+ARRY
 | 
					 | 
				
			||||||
FygiinddUCXNmmym5QzlqyjDsiCJ8AckHpXCLsDl6ez2PRIHSD3SwyNWQezT3zVL
 | 
					 | 
				
			||||||
yOf2hgVSEEOajBd8i6q8eODwRTusgFX+KJPhChFo9FJXb/5IC1tdGmpnc5mCtJ5D
 | 
					 | 
				
			||||||
YD7HWyoSbhruyzmuwzWdqLxdsC/DAgMBAAGjggF3MIIBczAfBgNVHSMEGDAWgBSt
 | 
					 | 
				
			||||||
vZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUmeRAX2sUXj4F2d3TY1T8Yrj3
 | 
					 | 
				
			||||||
AKwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEQYDVR0gBAow
 | 
					 | 
				
			||||||
CDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0
 | 
					 | 
				
			||||||
LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYIKwYBBQUHAQEEgaYw
 | 
					 | 
				
			||||||
gaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9BZGRUcnVz
 | 
					 | 
				
			||||||
dEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0cDovL2NydC51c2Vy
 | 
					 | 
				
			||||||
dHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRw
 | 
					 | 
				
			||||||
Oi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQCcNuNOrvGK
 | 
					 | 
				
			||||||
u2yXjI9LZ9Cf2ISqnyFfNaFbxCtjDei8d12nxDf9Sy2e6B1pocCEzNFti/OBy59L
 | 
					 | 
				
			||||||
dLBJKjHoN0DrH9mXoxoR1Sanbg+61b4s/bSRZNy+OxlQDXqV8wQTqbtHD4tc0azC
 | 
					 | 
				
			||||||
e3chUN1bq+70ptjUSlNrTa24yOfmUlhNQ0zCoiNPDsAgOa/fT0JbHtMJ9BgJWSrZ
 | 
					 | 
				
			||||||
6EoYvzL7+i1ki4fKWyvouAt+vhcSxwOCKa9Yr4WEXT0K3yNRw82vEL+AaXeRCk/l
 | 
					 | 
				
			||||||
uuGtm87fM04wO+mPZn+C+mv626PAcwDj1hKvTfIPWhRRH224hoFiB85ccsJP81cq
 | 
					 | 
				
			||||||
cdnUl4XmGFO3
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
 | 
					 | 
				
			||||||
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
 | 
					 | 
				
			||||||
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
 | 
					 | 
				
			||||||
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
 | 
					 | 
				
			||||||
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
 | 
					 | 
				
			||||||
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
 | 
					 | 
				
			||||||
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
 | 
					 | 
				
			||||||
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
 | 
					 | 
				
			||||||
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
 | 
					 | 
				
			||||||
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
 | 
					 | 
				
			||||||
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
 | 
					 | 
				
			||||||
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
 | 
					 | 
				
			||||||
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
 | 
					 | 
				
			||||||
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
 | 
					 | 
				
			||||||
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
 | 
					 | 
				
			||||||
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
 | 
					 | 
				
			||||||
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
 | 
					 | 
				
			||||||
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
 | 
					 | 
				
			||||||
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
 | 
					 | 
				
			||||||
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
 | 
					 | 
				
			||||||
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
 | 
					 | 
				
			||||||
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
 | 
					 | 
				
			||||||
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIE+zCCA+OgAwIBAgIQDJOL1Hip5tpyq5kwwV/lQzANBgkqhkiG9w0BAQUFADBz
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
 | 
					 | 
				
			||||||
VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEZMBcGA1UE
 | 
					 | 
				
			||||||
AxMQUG9zaXRpdmVTU0wgQ0EgMjAeFw0xMzA3MTIwMDAwMDBaFw0xNDA3MTIyMzU5
 | 
					 | 
				
			||||||
NTlaMFExITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEUMBIGA1UE
 | 
					 | 
				
			||||||
CxMLUG9zaXRpdmVTU0wxFjAUBgNVBAMTDWFwaS56dWxpcC5jb20wggEiMA0GCSqG
 | 
					 | 
				
			||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+GsCaNbs6bR4CB0MJ2NARH0JMoXsCVHHC
 | 
					 | 
				
			||||||
fT149arpZoAf9s4cmUgqe/qXl7jeh1Hb5UtARhchNMR/poFX9Dd73qTVfDEvtASW
 | 
					 | 
				
			||||||
ezpsEAB3KJQiISjUyL8xxRAggYf5AXtJ2QzaHoQ3sQk65lVuarB4aQwFB+SsbdtU
 | 
					 | 
				
			||||||
dDTHAgnJ3p8Vz4cFjus2n/EW+td5c74V7Y6nAj/ww8ygRRdAvfGmHa84ZHEu+xCI
 | 
					 | 
				
			||||||
5cnX0704hJETDfv1ELg257Rmg5pbwHfThSGs5KWv7AQqpLg+wNRD/s5LO1o6zB1z
 | 
					 | 
				
			||||||
Toidcq8HaD2/hS3oAQUibySRjieTHE1JU1ueqjfn0grrCpoSjgrDAgMBAAGjggGr
 | 
					 | 
				
			||||||
MIIBpzAfBgNVHSMEGDAWgBSZ5EBfaxRePgXZ3dNjVPxiuPcArDAdBgNVHQ4EFgQU
 | 
					 | 
				
			||||||
py+lc7gytud0YnB4ddplmEgkEeIwDgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQC
 | 
					 | 
				
			||||||
MAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFAGA1UdIARJMEcwOwYL
 | 
					 | 
				
			||||||
KwYBBAGyMQECAgcwLDAqBggrBgEFBQcCARYeaHR0cDovL3d3dy5wb3NpdGl2ZXNz
 | 
					 | 
				
			||||||
bC5jb20vQ1BTMAgGBmeBDAECATA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vY3Js
 | 
					 | 
				
			||||||
LmNvbW9kb2NhLmNvbS9Qb3NpdGl2ZVNTTENBMi5jcmwwbAYIKwYBBQUHAQEEYDBe
 | 
					 | 
				
			||||||
MDYGCCsGAQUFBzAChipodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9Qb3NpdGl2ZVNT
 | 
					 | 
				
			||||||
TENBMi5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAr
 | 
					 | 
				
			||||||
BgNVHREEJDAigg1hcGkuenVsaXAuY29tghF3d3cuYXBpLnp1bGlwLmNvbTANBgkq
 | 
					 | 
				
			||||||
hkiG9w0BAQUFAAOCAQEAQKpkB8eRq5K2KBMVFolxSqix4qWo/uPiOQU6kbjkJNdK
 | 
					 | 
				
			||||||
P1Wg+p1R1KsLTLDEZmqTnfIBluez/RqfEoPdh+cF2e0GP55Y2ogno+89oaW4ijUr
 | 
					 | 
				
			||||||
IgTor/b1ZVv+yQIi/u27hLpq/h5E5ZM6HpmQ5YcA4z3MY7VoXNxYY5iO34YzuD0n
 | 
					 | 
				
			||||||
emoDuM1JJuGTzPkxE/dUzRU7GUmi5cXQgdGQ9lvutI/DuyZsDJV54TW2882cpW82
 | 
					 | 
				
			||||||
5x4a77Esvx7VlqBC5KxN/NPN/ZwIs5vl4F1+/sf2Tr7oMDkZ4Tc944mkj5MAbhhm
 | 
					 | 
				
			||||||
JZV4K+MlPPP7VSWOr+y+lMHAAqk7nhBi8MPP4XOo0A==
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFSzCCBDOgAwIBAgIQC9+c6kd+aB3quGVISZS4fzANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNTAyMDYwMDAwMDBaFw0xNzAyMDkxMjAwMDBa
 | 
				
			||||||
 | 
					MG4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGzAZBgNVBAMTEmNo
 | 
				
			||||||
 | 
					YXQuZHJvcGJveGVyLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
 | 
				
			||||||
 | 
					AO8HnnyDj64aGeEoFewFuASlpw8YzBnbF9E1A4CFdevwXCfHhDUXUZd3nGwHTlUc
 | 
				
			||||||
 | 
					Yq/Yn6iDc0S08ZTM5OJmeeNxsZojHK6CaZjKEiRkerRVwq7AWEPvJWdVlmRjDXMX
 | 
				
			||||||
 | 
					rpGlL44L9voeKDr4ueq9uP85QIffbtF7wRFjxHH5ULPxcVFGeFsShaaWkK1YdVl0
 | 
				
			||||||
 | 
					C0KarUBxX6Dz0J5KB9Am2qGz7fEGmMeYmLjUQEohvD+NLnSHIH1gCCrnMDyp7SX4
 | 
				
			||||||
 | 
					iVlSwJBfZJB71uTB2+9CX3k+jgMA6l+KrjyUoFTJmxGkcwyEqKoCoJG2mL81L0fZ
 | 
				
			||||||
 | 
					Yx55K1kJh6qBXAg4JIwMD7UCAwEAAaOCAeEwggHdMB8GA1UdIwQYMBaAFFFo/5Cv
 | 
				
			||||||
 | 
					Agd1PMzZZWRiohK4WXI7MB0GA1UdDgQWBBQgWnzJolAbDp9oilo3SuR3LPcSIDAd
 | 
				
			||||||
 | 
					BgNVHREEFjAUghJjaGF0LmRyb3Bib3hlci5uZXQwDgYDVR0PAQH/BAQDAgWgMB0G
 | 
				
			||||||
 | 
					A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5o
 | 
				
			||||||
 | 
					dHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3JsMDSg
 | 
				
			||||||
 | 
					MqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMu
 | 
				
			||||||
 | 
					Y3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBz
 | 
				
			||||||
 | 
					Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEF
 | 
				
			||||||
 | 
					BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRw
 | 
				
			||||||
 | 
					Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCa
 | 
				
			||||||
 | 
					dUkIIbDl2iEmWE//z9jPgFboPzkzDR+03cBuvBRkqQ8SD/+pfB/TiZQerKS+xcy7
 | 
				
			||||||
 | 
					NB/0kvBnMqGsknXYL9w2rGFv0R/sDHDCiwtxh+1mwS9r+AvmCRkA3T7mcSO3O9lI
 | 
				
			||||||
 | 
					dIbrIhPJHvmyac7rCAvmW1i4KTbCSaBOLLmSnXjLpa6E3zrv4Xn2k8u6eOCLNgqV
 | 
				
			||||||
 | 
					89qswf/pYZcvHKgyFZ9PdhwXxV9MO1c9U/GCWOZWXextAtmAvbxJDkc2JqT2mS1D
 | 
				
			||||||
 | 
					8GvkaMudfm1o/dYvv9F0tgsh4UGpWnvlp8IXZil2Ik4m2yfc37MoNgpNa0ytEJUp
 | 
				
			||||||
 | 
					tFDLVilooSEBYckHRdm+
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFQTCCBCmgAwIBAgIQAiBxGEAt+S6rlqaxlh4i9TANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFjAUBgNVBAMTDWdp
 | 
				
			||||||
 | 
					dC56dWxpcC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgo7bC
 | 
				
			||||||
 | 
					QDUprWNwBgGI1uytomGzO141oZQq0TY4VI/EXiAQ1gClyJ6NgEBPD+RVK4/82JIW
 | 
				
			||||||
 | 
					RLkztIaM3uyO6JXOBzDifehI32l2Tqj0ZtvipOzE/IJyucAXvVocHCtseKpCcUB0
 | 
				
			||||||
 | 
					pSXhie2RH9y0cTRZHMY7OW5N3+SE+W4W57eo0QCHzhKetcD0AOdIx1rDltuyPHCr
 | 
				
			||||||
 | 
					xybH4LIYTMsE71Nx7RZI3KJvlWUNQtvY0bF9Xy/2Ag47mLf1vlpWkvWRNTWd6t5v
 | 
				
			||||||
 | 
					7zcNAbohYAaeGrUrhFbTojIjzd31BioZPY5N4XJYDQCtlk+g3EhsarPRAsJ3+C/e
 | 
				
			||||||
 | 
					HJC3JVYxEtScUlULAgMBAAGjggHcMIIB2DAfBgNVHSMEGDAWgBRRaP+QrwIHdTzM
 | 
				
			||||||
 | 
					2WVkYqISuFlyOzAdBgNVHQ4EFgQU/AFjeJNjGOJat2Ng5D/djicf7lIwGAYDVR0R
 | 
				
			||||||
 | 
					BBEwD4INZ2l0Lnp1bGlwLm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
 | 
				
			||||||
 | 
					KwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6Ly9jcmwz
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwNKAyoDCGLmh0dHA6
 | 
				
			||||||
 | 
					Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwQgYDVR0g
 | 
				
			||||||
 | 
					BDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGln
 | 
				
			||||||
 | 
					aWNlcnQuY29tL0NQUzCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRw
 | 
				
			||||||
 | 
					Oi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRz
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0Eu
 | 
				
			||||||
 | 
					Y3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAJUD9412uJCVG5lZ
 | 
				
			||||||
 | 
					AYWKQ101Mx5+IcbiNhFpyXiPhmPDHD+qAZUCoFbdcPA9U9AOwcI55+Z6hZ7bcYhB
 | 
				
			||||||
 | 
					KOSMEf60hwQbN1CdvR6oV25DZ6QbBF8R6PLMEym/T4auVj98wA1J1kgVS33SRoWt
 | 
				
			||||||
 | 
					PWa4eVXxJL/977CMJNoYh5hjmxivXq7swIrn+xA4D79euFPZdzqov6+oKtzRQNY5
 | 
				
			||||||
 | 
					qATfF4GD4Sj6qZqIetuIv42BcUGd+s0VH6GMDvKlcDA51q7N8WVoGrsIRHmOV2qF
 | 
				
			||||||
 | 
					fNSpzreV9YDFOv0KUJCThdJiwdJVNS/ZgE1fNvyhCNcbISBkfkSR8rROu5LY0xDB
 | 
				
			||||||
 | 
					51QMgbM=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					N CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										31
									
								
								puppet/zulip_internal/files/certs/git.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								puppet/zulip_internal/files/certs/git.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFQTCCBCmgAwIBAgIQAiBxGEAt+S6rlqaxlh4i9TANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGkxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFjAUBgNVBAMTDWdp
 | 
				
			||||||
 | 
					dC56dWxpcC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgo7bC
 | 
				
			||||||
 | 
					QDUprWNwBgGI1uytomGzO141oZQq0TY4VI/EXiAQ1gClyJ6NgEBPD+RVK4/82JIW
 | 
				
			||||||
 | 
					RLkztIaM3uyO6JXOBzDifehI32l2Tqj0ZtvipOzE/IJyucAXvVocHCtseKpCcUB0
 | 
				
			||||||
 | 
					pSXhie2RH9y0cTRZHMY7OW5N3+SE+W4W57eo0QCHzhKetcD0AOdIx1rDltuyPHCr
 | 
				
			||||||
 | 
					xybH4LIYTMsE71Nx7RZI3KJvlWUNQtvY0bF9Xy/2Ag47mLf1vlpWkvWRNTWd6t5v
 | 
				
			||||||
 | 
					7zcNAbohYAaeGrUrhFbTojIjzd31BioZPY5N4XJYDQCtlk+g3EhsarPRAsJ3+C/e
 | 
				
			||||||
 | 
					HJC3JVYxEtScUlULAgMBAAGjggHcMIIB2DAfBgNVHSMEGDAWgBRRaP+QrwIHdTzM
 | 
				
			||||||
 | 
					2WVkYqISuFlyOzAdBgNVHQ4EFgQU/AFjeJNjGOJat2Ng5D/djicf7lIwGAYDVR0R
 | 
				
			||||||
 | 
					BBEwD4INZ2l0Lnp1bGlwLm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI
 | 
				
			||||||
 | 
					KwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6Ly9jcmwz
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwNKAyoDCGLmh0dHA6
 | 
				
			||||||
 | 
					Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwQgYDVR0g
 | 
				
			||||||
 | 
					BDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGln
 | 
				
			||||||
 | 
					aWNlcnQuY29tL0NQUzCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzABhhhodHRw
 | 
				
			||||||
 | 
					Oi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9jYWNlcnRz
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2VydmVyQ0Eu
 | 
				
			||||||
 | 
					Y3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBAJUD9412uJCVG5lZ
 | 
				
			||||||
 | 
					AYWKQ101Mx5+IcbiNhFpyXiPhmPDHD+qAZUCoFbdcPA9U9AOwcI55+Z6hZ7bcYhB
 | 
				
			||||||
 | 
					KOSMEf60hwQbN1CdvR6oV25DZ6QbBF8R6PLMEym/T4auVj98wA1J1kgVS33SRoWt
 | 
				
			||||||
 | 
					PWa4eVXxJL/977CMJNoYh5hjmxivXq7swIrn+xA4D79euFPZdzqov6+oKtzRQNY5
 | 
				
			||||||
 | 
					qATfF4GD4Sj6qZqIetuIv42BcUGd+s0VH6GMDvKlcDA51q7N8WVoGrsIRHmOV2qF
 | 
				
			||||||
 | 
					fNSpzreV9YDFOv0KUJCThdJiwdJVNS/ZgE1fNvyhCNcbISBkfkSR8rROu5LY0xDB
 | 
				
			||||||
 | 
					51QMgbM=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFRTCCBC2gAwIBAgIQDDxR9Pi3OvaLaxM1QQINATANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGDAWBgNVBAMTD211
 | 
				
			||||||
 | 
					bmluLnp1bGlwLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmH
 | 
				
			||||||
 | 
					EH72mRFJapF9jJAHZs1dDxka0DD6vEzIlUPylq009VZguROUm1/2/37vtOaZdoRP
 | 
				
			||||||
 | 
					zJ+LNq1Aeam3JdVuNd2EA4Rl0UbZM1P+yMggfffMzLczQRTumSCaOPq5SMqnS0az
 | 
				
			||||||
 | 
					2UITCxknaQmW8g4nbLElChbW7GYFIYxSizfz5yTqV25mqMN1IIDpRJghGU6154Pk
 | 
				
			||||||
 | 
					VSPWvynzWmDAW9UJDBT9dqJp3TAFKNzQGad1ERkkPr2XXd71KjjLFfqKiVCAK4oq
 | 
				
			||||||
 | 
					r281CQEHh7uUPVq0zrwLvtCPaMx7Zq+0a82/ABnA2wEDiptSXZ6K/2LF/otGzXsy
 | 
				
			||||||
 | 
					udTRD/0hTBQ0R5Y9DscCAwEAAaOCAd4wggHaMB8GA1UdIwQYMBaAFFFo/5CvAgd1
 | 
				
			||||||
 | 
					PMzZZWRiohK4WXI7MB0GA1UdDgQWBBRsJooKV4ptTkrJjKsAJ7CwyvzzqTAaBgNV
 | 
				
			||||||
 | 
					HREEEzARgg9tdW5pbi56dWxpcC5uZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
 | 
				
			||||||
 | 
					MBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8v
 | 
				
			||||||
 | 
					Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMDSgMqAwhi5o
 | 
				
			||||||
 | 
					dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMEIG
 | 
				
			||||||
 | 
					A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYY
 | 
				
			||||||
 | 
					aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2Fj
 | 
				
			||||||
 | 
					ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZl
 | 
				
			||||||
 | 
					ckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAjA309Hd9C
 | 
				
			||||||
 | 
					lrPzMKjJTXP6G9PUH3YpkUVdRitV5lrNZwfQL5SomehxL9KG58Obvzuae0SJMWfE
 | 
				
			||||||
 | 
					ODP6jkPywbv0n4RKaQEQwB80CZj4nKqrnsJGToSVWE+Wso/E6tBF3NjFqZzVNok2
 | 
				
			||||||
 | 
					+ql6rElmI9H0n7be6x78p4TGqzEEbnS56hlppWXYQXPWi40vJSQCo8/YIy62L6wj
 | 
				
			||||||
 | 
					Ulaqdx+sqxE7qR/AwhWlsFpcKP2XRN91fzPtKj/mlGyyYk6r1gnhoqvSlQqqucKs
 | 
				
			||||||
 | 
					UJ60uG8I4hfwbGIJyuCX3ipvhl9RpH+UL4MQCPD8sKxQfnn7T5iEQylWubCsU3K5
 | 
				
			||||||
 | 
					ORxuyUfWjLpo
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										31
									
								
								puppet/zulip_internal/files/certs/munin.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								puppet/zulip_internal/files/certs/munin.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFRTCCBC2gAwIBAgIQDDxR9Pi3OvaLaxM1QQINATANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGDAWBgNVBAMTD211
 | 
				
			||||||
 | 
					bmluLnp1bGlwLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmH
 | 
				
			||||||
 | 
					EH72mRFJapF9jJAHZs1dDxka0DD6vEzIlUPylq009VZguROUm1/2/37vtOaZdoRP
 | 
				
			||||||
 | 
					zJ+LNq1Aeam3JdVuNd2EA4Rl0UbZM1P+yMggfffMzLczQRTumSCaOPq5SMqnS0az
 | 
				
			||||||
 | 
					2UITCxknaQmW8g4nbLElChbW7GYFIYxSizfz5yTqV25mqMN1IIDpRJghGU6154Pk
 | 
				
			||||||
 | 
					VSPWvynzWmDAW9UJDBT9dqJp3TAFKNzQGad1ERkkPr2XXd71KjjLFfqKiVCAK4oq
 | 
				
			||||||
 | 
					r281CQEHh7uUPVq0zrwLvtCPaMx7Zq+0a82/ABnA2wEDiptSXZ6K/2LF/otGzXsy
 | 
				
			||||||
 | 
					udTRD/0hTBQ0R5Y9DscCAwEAAaOCAd4wggHaMB8GA1UdIwQYMBaAFFFo/5CvAgd1
 | 
				
			||||||
 | 
					PMzZZWRiohK4WXI7MB0GA1UdDgQWBBRsJooKV4ptTkrJjKsAJ7CwyvzzqTAaBgNV
 | 
				
			||||||
 | 
					HREEEzARgg9tdW5pbi56dWxpcC5uZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
 | 
				
			||||||
 | 
					MBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8v
 | 
				
			||||||
 | 
					Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMDSgMqAwhi5o
 | 
				
			||||||
 | 
					dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMEIG
 | 
				
			||||||
 | 
					A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYY
 | 
				
			||||||
 | 
					aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2Fj
 | 
				
			||||||
 | 
					ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZl
 | 
				
			||||||
 | 
					ckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAjA309Hd9C
 | 
				
			||||||
 | 
					lrPzMKjJTXP6G9PUH3YpkUVdRitV5lrNZwfQL5SomehxL9KG58Obvzuae0SJMWfE
 | 
				
			||||||
 | 
					ODP6jkPywbv0n4RKaQEQwB80CZj4nKqrnsJGToSVWE+Wso/E6tBF3NjFqZzVNok2
 | 
				
			||||||
 | 
					+ql6rElmI9H0n7be6x78p4TGqzEEbnS56hlppWXYQXPWi40vJSQCo8/YIy62L6wj
 | 
				
			||||||
 | 
					Ulaqdx+sqxE7qR/AwhWlsFpcKP2XRN91fzPtKj/mlGyyYk6r1gnhoqvSlQqqucKs
 | 
				
			||||||
 | 
					UJ60uG8I4hfwbGIJyuCX3ipvhl9RpH+UL4MQCPD8sKxQfnn7T5iEQylWubCsU3K5
 | 
				
			||||||
 | 
					ORxuyUfWjLpo
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFRzCCBC+gAwIBAgIQCwfY+SvxDTFK0KY29dqHWjANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGTAXBgNVBAMTEG5h
 | 
				
			||||||
 | 
					Z2lvcy56dWxpcC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCy
 | 
				
			||||||
 | 
					J6F6KjG/Y1vf3oj947a+otyc/BFH81K9AsZUrL46kXoCkdr6SJqJDKYLn/adv+OI
 | 
				
			||||||
 | 
					GTDo8LpbISE2FkviRFgUEIAkHcxdF4UMv1fpby2VcYleFigD2Fn+LkWcCpqk9uRL
 | 
				
			||||||
 | 
					VhAgbZdXLLw0LtTMp0kESO+DsjpfbwjNP+POZBLN96PoOToiUmNJKwhLucckmo/K
 | 
				
			||||||
 | 
					QrEfwRdDxJfD12NYCl8ZEOFfQEinWmstvschCM1LOeZTBDBHFXOvi1xhPu8utpHJ
 | 
				
			||||||
 | 
					xdibN0vWn17Cole0Blris3sT34KA/FRswCJ4jTxtL58WIE19YLiLDoP3kDNuNjZc
 | 
				
			||||||
 | 
					uhXk/sgqrGqam5GQfUOhAgMBAAGjggHfMIIB2zAfBgNVHSMEGDAWgBRRaP+QrwIH
 | 
				
			||||||
 | 
					dTzM2WVkYqISuFlyOzAdBgNVHQ4EFgQUGk12Sw4Clj8YyjOggnJ7LXTXRoAwGwYD
 | 
				
			||||||
 | 
					VR0RBBQwEoIQbmFnaW9zLnp1bGlwLm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l
 | 
				
			||||||
 | 
					BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6
 | 
				
			||||||
 | 
					Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwNKAyoDCG
 | 
				
			||||||
 | 
					Lmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmww
 | 
				
			||||||
 | 
					QgYDVR0gBDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tL0NQUzCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzAB
 | 
				
			||||||
 | 
					hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9j
 | 
				
			||||||
 | 
					YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2Vy
 | 
				
			||||||
 | 
					dmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBACsGRuZG
 | 
				
			||||||
 | 
					SVqbo/VtJJCOLSS4+IeyaPWqvH0e7Nlt4NPrgZVoI+JBPhwEnfbtGPX4epIu+gRF
 | 
				
			||||||
 | 
					1Zazk0E9nGUh5AUatruz0wq/FCj4eg+koV1XJLwlJde/s2IgEilG15wBWhH02uJo
 | 
				
			||||||
 | 
					oM+wScbr4rPxwgB4Dytz/HAYIXzMyPdYr0/zFGBpCtHIDd5E1mFyCn+0tCh0TRBm
 | 
				
			||||||
 | 
					YleHUA6A7CXq9iKNknIpJw/BDOYLtNz91qCBL4U3sB9kfJ4HEF9jC8/HhlW6IH1r
 | 
				
			||||||
 | 
					B5zjnj4D0FDyJSzBF44HUbzCxp7t/rEnQTASSdQaMcm9T7rqw8doJ8umnDLLeqp5
 | 
				
			||||||
 | 
					2IeiKC3ePDOsopE=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -1,36 +1,31 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
MIIGVDCCBTygAwIBAgIDC9I3MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
 | 
					MIIFRzCCBC+gAwIBAgIQCwfY+SvxDTFK0KY29dqHWjANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwOTA0MTcxMDI4
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
WhcNMTQwOTA1MTA1ODI3WjBoMRkwFwYDVQQNExBncWdkOTFoVlNLUUw4d2k2MQsw
 | 
					MGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
CQYDVQQGEwJVUzEZMBcGA1UEAxMQbmFnaW9zLnp1bGlwLm5ldDEjMCEGCSqGSIb3
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGTAXBgNVBAMTEG5h
 | 
				
			||||||
DQEJARYUaG9zdG1hc3RlckB6dWxpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
 | 
					Z2lvcy56dWxpcC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCy
 | 
				
			||||||
DwAwggEKAoIBAQC3r6IfMWzcOZzQUlY3AU5P89WsWt0JLjCPFhxCLplVfR9a0VZk
 | 
					J6F6KjG/Y1vf3oj947a+otyc/BFH81K9AsZUrL46kXoCkdr6SJqJDKYLn/adv+OI
 | 
				
			||||||
2e7xiOuldoXSkwuzXPATQHPlmsbJdN9g86agj9VLhfiIr7rZV3Fx4IUJqaAE62eB
 | 
					GTDo8LpbISE2FkviRFgUEIAkHcxdF4UMv1fpby2VcYleFigD2Fn+LkWcCpqk9uRL
 | 
				
			||||||
rMdPYfP5EjB3zMSuJYFldqsLFfHvucBqGvM2b9F7iuDFHaeQk9xETeKx5fADUdI7
 | 
					VhAgbZdXLLw0LtTMp0kESO+DsjpfbwjNP+POZBLN96PoOToiUmNJKwhLucckmo/K
 | 
				
			||||||
FqLyL3mWmfm8vS9mNLOdkxN93D6R6zvIwUUvDya9wYl5b1D3IAL1ADaMsAGqbihW
 | 
					QrEfwRdDxJfD12NYCl8ZEOFfQEinWmstvschCM1LOeZTBDBHFXOvi1xhPu8utpHJ
 | 
				
			||||||
N5Prdv2d+v4S/OiA+x9fM26WRVr4oFfSNsVQzHOVEwuuazXx8IgN2NgjcAMmbJBz
 | 
					xdibN0vWn17Cole0Blris3sT34KA/FRswCJ4jTxtL58WIE19YLiLDoP3kDNuNjZc
 | 
				
			||||||
dWzjy1XOek07vEKo5D7Quh4IxuQXF2GFbExxAgMBAAGjggLgMIIC3DAJBgNVHRME
 | 
					uhXk/sgqrGqam5GQfUOhAgMBAAGjggHfMIIB2zAfBgNVHSMEGDAWgBRRaP+QrwIH
 | 
				
			||||||
AjAAMAsGA1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQU
 | 
					dTzM2WVkYqISuFlyOzAdBgNVHQ4EFgQUGk12Sw4Clj8YyjOggnJ7LXTXRoAwGwYD
 | 
				
			||||||
ydhvTxMKSA0pXcaM0rZaN3IxCRswHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xk
 | 
					VR0RBBQwEoIQbmFnaW9zLnp1bGlwLm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l
 | 
				
			||||||
Lu8OLEUwJgYDVR0RBB8wHYIQbmFnaW9zLnp1bGlwLm5ldIIJenVsaXAubmV0MIIB
 | 
					BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMHUGA1UdHwRuMGwwNKAyoDCGLmh0dHA6
 | 
				
			||||||
VgYDVR0gBIIBTTCCAUkwCAYGZ4EMAQIBMIIBOwYLKwYBBAGBtTcBAgMwggEqMC4G
 | 
					Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmwwNKAyoDCG
 | 
				
			||||||
CCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMIH3
 | 
					Lmh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWhhLXNlcnZlci1nMi5jcmww
 | 
				
			||||||
BggrBgEFBQcCAjCB6jAnFiBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
 | 
					QgYDVR0gBDswOTA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93
 | 
				
			||||||
eTADAgEBGoG+VGhpcyBjZXJ0aWZpY2F0ZSB3YXMgaXNzdWVkIGFjY29yZGluZyB0
 | 
					d3cuZGlnaWNlcnQuY29tL0NQUzCBgwYIKwYBBQUHAQEEdzB1MCQGCCsGAQUFBzAB
 | 
				
			||||||
byB0aGUgQ2xhc3MgMSBWYWxpZGF0aW9uIHJlcXVpcmVtZW50cyBvZiB0aGUgU3Rh
 | 
					hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTQYIKwYBBQUHMAKGQWh0dHA6Ly9j
 | 
				
			||||||
cnRDb20gQ0EgcG9saWN5LCByZWxpYW5jZSBvbmx5IGZvciB0aGUgaW50ZW5kZWQg
 | 
					YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJIaWdoQXNzdXJhbmNlU2Vy
 | 
				
			||||||
cHVycG9zZSBpbiBjb21wbGlhbmNlIG9mIHRoZSByZWx5aW5nIHBhcnR5IG9ibGln
 | 
					dmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggEBACsGRuZG
 | 
				
			||||||
YXRpb25zLjA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLnN0YXJ0c3NsLmNv
 | 
					SVqbo/VtJJCOLSS4+IeyaPWqvH0e7Nlt4NPrgZVoI+JBPhwEnfbtGPX4epIu+gRF
 | 
				
			||||||
bS9jcnQxLWNybC5jcmwwgY4GCCsGAQUFBwEBBIGBMH8wOQYIKwYBBQUHMAGGLWh0
 | 
					1Zazk0E9nGUh5AUatruz0wq/FCj4eg+koV1XJLwlJde/s2IgEilG15wBWhH02uJo
 | 
				
			||||||
dHA6Ly9vY3NwLnN0YXJ0c3NsLmNvbS9zdWIvY2xhc3MxL3NlcnZlci9jYTBCBggr
 | 
					oM+wScbr4rPxwgB4Dytz/HAYIXzMyPdYr0/zFGBpCtHIDd5E1mFyCn+0tCh0TRBm
 | 
				
			||||||
BgEFBQcwAoY2aHR0cDovL2FpYS5zdGFydHNzbC5jb20vY2VydHMvc3ViLmNsYXNz
 | 
					YleHUA6A7CXq9iKNknIpJw/BDOYLtNz91qCBL4U3sB9kfJ4HEF9jC8/HhlW6IH1r
 | 
				
			||||||
MS5zZXJ2ZXIuY2EuY3J0MCMGA1UdEgQcMBqGGGh0dHA6Ly93d3cuc3RhcnRzc2wu
 | 
					B5zjnj4D0FDyJSzBF44HUbzCxp7t/rEnQTASSdQaMcm9T7rqw8doJ8umnDLLeqp5
 | 
				
			||||||
Y29tLzANBgkqhkiG9w0BAQUFAAOCAQEAIT+IkU07y1M1LNVr6CMjqz3voIYkQPNX
 | 
					2IeiKC3ePDOsopE=
 | 
				
			||||||
SssClaGMfyi3QSPVhniMUZJWiHvPLdLsDP1fbI4lRGAuIjHv6kAwGD1ZLrMTCTMl
 | 
					 | 
				
			||||||
pHD0Jnlf5rtWFzklWAt/dDslauaC7eYgMFx1fHja1vJu9QXUaTXas6GGxKfNYma9
 | 
					 | 
				
			||||||
OQgjxnEKjTciyyxnAA+i5d4I/eaJHeX79+PpyCULknDjrfBF1wAPakq9WJx+yzlt
 | 
					 | 
				
			||||||
pz9+3Ggdfhhecaixb/StyXYT8tXnQy+aTnLZqh7mmPWGd01oD5AFMwyCRr5nzepj
 | 
					 | 
				
			||||||
6R8DkHRe/3LFg4YDUpY8WORLTSAeQHVA3inGymsPlVJdmVSq///HdA==
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,116 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIGVjCCBT6gAwIBAgIDCxnMMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
 | 
					 | 
				
			||||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
 | 
					 | 
				
			||||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
 | 
					 | 
				
			||||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwNzEyMTUwMjQ1
 | 
					 | 
				
			||||||
WhcNMTQwNzEyMjI0NDM0WjBpMRkwFwYDVQQNExBXODl0UjVjVkIyNTZ4ZzFwMQsw
 | 
					 | 
				
			||||||
CQYDVQQGEwJVUzEaMBgGA1UEAxMRc3RhZ2luZy56dWxpcC5jb20xIzAhBgkqhkiG
 | 
					 | 
				
			||||||
9w0BCQEWFGhvc3RtYXN0ZXJAenVsaXAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
 | 
					 | 
				
			||||||
AQ8AMIIBCgKCAQEA+omI0rp0LrwoxQ3vFPQDgqyOeHfoLLpSSqCLRZv+oH9aPscg
 | 
					 | 
				
			||||||
oTb2ua1VJjPGjBSKw7tsBitCLF9BEsDXZc0eQa6gqFzTEwC4n7xdqr9t0qxrF7ht
 | 
					 | 
				
			||||||
Uy9AJZZ0GuWkzk+qSMgl+/iRXv9PzCU/UnGNxI1AqiJUCRXcItriFbb5+mgOQlS8
 | 
					 | 
				
			||||||
EYYGnNR5mtU29UQadNiDzp73QgkCGfUxTBvJOcLntZRVAI9ElEcN4y2wfLcBhKJT
 | 
					 | 
				
			||||||
EE134j6JmY4Z7/UtyJa3gas3CM4Z2ttx5pEqT+qten7+/TdpkTj4R1BvYvPSRzDZ
 | 
					 | 
				
			||||||
TisDb0xa67CZ7bNf/Tyl9UeXRqAUix38TPuJ8QIDAQABo4IC4TCCAt0wCQYDVR0T
 | 
					 | 
				
			||||||
BAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYE
 | 
					 | 
				
			||||||
FHQVTfN38Y2YZmpjAHBIp/aLDSOyMB8GA1UdIwQYMBaAFOtCNNCYsKuf9BtrCPfM
 | 
					 | 
				
			||||||
ZC7vDixFMCcGA1UdEQQgMB6CEXN0YWdpbmcuenVsaXAuY29tggl6dWxpcC5jb20w
 | 
					 | 
				
			||||||
ggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgEwggE7BgsrBgEEAYG1NwECAzCCASow
 | 
					 | 
				
			||||||
LgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYw
 | 
					 | 
				
			||||||
gfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9y
 | 
					 | 
				
			||||||
aXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3JkaW5n
 | 
					 | 
				
			||||||
IHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRoZSBT
 | 
					 | 
				
			||||||
dGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRl
 | 
					 | 
				
			||||||
ZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkgb2Js
 | 
					 | 
				
			||||||
aWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wu
 | 
					 | 
				
			||||||
Y29tL2NydDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcwAYYt
 | 
					 | 
				
			||||||
aHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczEvc2VydmVyL2NhMEIG
 | 
					 | 
				
			||||||
CCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xh
 | 
					 | 
				
			||||||
c3MxLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFydHNz
 | 
					 | 
				
			||||||
bC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQCTTSbioYG8QJfK6Yfc3ijdS2oOh8AI
 | 
					 | 
				
			||||||
Gf3IN1TpmWAM8ijhDsDX0E8/Us6PHCwsg+yLuHI+92/MtHHSMnfew5HenTol6hNY
 | 
					 | 
				
			||||||
CDPnaHd1UtDfp6/yp8U0iQMWIjxecL46IAyjdD9tX43dLhL5fziQYEJ2rjFHtK8J
 | 
					 | 
				
			||||||
FBRg9QZI536BJ4aPfcFWwWtaYqWB7Nib1n86SKCPl0Tn1HfFJ+j0vkh0EwoJ3y3z
 | 
					 | 
				
			||||||
8VbJNwI0DxYMUDN2burWvEzUfAtNh2c7vuHhY6q96kNTMmbed/1DPUWWVyXKYtVc
 | 
					 | 
				
			||||||
FC9Q+3yQ3JqCJ1XoV3OxiYzdQnNn8WQGsEx1pxD9D6mHYnffeOUlHqhB
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
 | 
					 | 
				
			||||||
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
 | 
					 | 
				
			||||||
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
 | 
					 | 
				
			||||||
dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
 | 
					 | 
				
			||||||
jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
 | 
					 | 
				
			||||||
IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
 | 
					 | 
				
			||||||
YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
 | 
					 | 
				
			||||||
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
 | 
					 | 
				
			||||||
gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
 | 
					 | 
				
			||||||
pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
 | 
					 | 
				
			||||||
kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
 | 
					 | 
				
			||||||
ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
 | 
					 | 
				
			||||||
xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
 | 
					 | 
				
			||||||
AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
 | 
					 | 
				
			||||||
VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
 | 
					 | 
				
			||||||
F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
 | 
					 | 
				
			||||||
L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
 | 
					 | 
				
			||||||
YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
 | 
					 | 
				
			||||||
dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
 | 
					 | 
				
			||||||
c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
 | 
					 | 
				
			||||||
BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
 | 
					 | 
				
			||||||
BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
 | 
					 | 
				
			||||||
LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
 | 
					 | 
				
			||||||
tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
 | 
					 | 
				
			||||||
xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
 | 
					 | 
				
			||||||
xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
 | 
					 | 
				
			||||||
t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
 | 
					 | 
				
			||||||
RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
 | 
					 | 
				
			||||||
YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
 | 
					 | 
				
			||||||
WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
 | 
					 | 
				
			||||||
SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
 | 
					 | 
				
			||||||
wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
 | 
					 | 
				
			||||||
p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
 | 
					 | 
				
			||||||
0q6Dp6jOW6c=
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
 | 
					 | 
				
			||||||
MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
 | 
					 | 
				
			||||||
Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
 | 
					 | 
				
			||||||
dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
 | 
					 | 
				
			||||||
U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
 | 
					 | 
				
			||||||
cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
 | 
					 | 
				
			||||||
A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
 | 
					 | 
				
			||||||
pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
 | 
					 | 
				
			||||||
OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
 | 
					 | 
				
			||||||
Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
 | 
					 | 
				
			||||||
Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
 | 
					 | 
				
			||||||
HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
 | 
					 | 
				
			||||||
Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
 | 
					 | 
				
			||||||
+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
 | 
					 | 
				
			||||||
Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
 | 
					 | 
				
			||||||
Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
 | 
					 | 
				
			||||||
26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
 | 
					 | 
				
			||||||
AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
 | 
					 | 
				
			||||||
FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
 | 
					 | 
				
			||||||
ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
 | 
					 | 
				
			||||||
LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
 | 
					 | 
				
			||||||
BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
 | 
					 | 
				
			||||||
Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
 | 
					 | 
				
			||||||
dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
 | 
					 | 
				
			||||||
cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
 | 
					 | 
				
			||||||
YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
 | 
					 | 
				
			||||||
dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
 | 
					 | 
				
			||||||
bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
 | 
					 | 
				
			||||||
YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
 | 
					 | 
				
			||||||
TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
 | 
					 | 
				
			||||||
9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
 | 
					 | 
				
			||||||
jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
 | 
					 | 
				
			||||||
FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
 | 
					 | 
				
			||||||
ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
 | 
					 | 
				
			||||||
ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
 | 
					 | 
				
			||||||
EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
 | 
					 | 
				
			||||||
L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
 | 
					 | 
				
			||||||
yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
 | 
					 | 
				
			||||||
O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
 | 
					 | 
				
			||||||
um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
 | 
					 | 
				
			||||||
NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIGVjCCBT6gAwIBAgIDCxnMMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
 | 
					 | 
				
			||||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
 | 
					 | 
				
			||||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
 | 
					 | 
				
			||||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwNzEyMTUwMjQ1
 | 
					 | 
				
			||||||
WhcNMTQwNzEyMjI0NDM0WjBpMRkwFwYDVQQNExBXODl0UjVjVkIyNTZ4ZzFwMQsw
 | 
					 | 
				
			||||||
CQYDVQQGEwJVUzEaMBgGA1UEAxMRc3RhZ2luZy56dWxpcC5jb20xIzAhBgkqhkiG
 | 
					 | 
				
			||||||
9w0BCQEWFGhvc3RtYXN0ZXJAenVsaXAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
 | 
					 | 
				
			||||||
AQ8AMIIBCgKCAQEA+omI0rp0LrwoxQ3vFPQDgqyOeHfoLLpSSqCLRZv+oH9aPscg
 | 
					 | 
				
			||||||
oTb2ua1VJjPGjBSKw7tsBitCLF9BEsDXZc0eQa6gqFzTEwC4n7xdqr9t0qxrF7ht
 | 
					 | 
				
			||||||
Uy9AJZZ0GuWkzk+qSMgl+/iRXv9PzCU/UnGNxI1AqiJUCRXcItriFbb5+mgOQlS8
 | 
					 | 
				
			||||||
EYYGnNR5mtU29UQadNiDzp73QgkCGfUxTBvJOcLntZRVAI9ElEcN4y2wfLcBhKJT
 | 
					 | 
				
			||||||
EE134j6JmY4Z7/UtyJa3gas3CM4Z2ttx5pEqT+qten7+/TdpkTj4R1BvYvPSRzDZ
 | 
					 | 
				
			||||||
TisDb0xa67CZ7bNf/Tyl9UeXRqAUix38TPuJ8QIDAQABo4IC4TCCAt0wCQYDVR0T
 | 
					 | 
				
			||||||
BAIwADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYE
 | 
					 | 
				
			||||||
FHQVTfN38Y2YZmpjAHBIp/aLDSOyMB8GA1UdIwQYMBaAFOtCNNCYsKuf9BtrCPfM
 | 
					 | 
				
			||||||
ZC7vDixFMCcGA1UdEQQgMB6CEXN0YWdpbmcuenVsaXAuY29tggl6dWxpcC5jb20w
 | 
					 | 
				
			||||||
ggFWBgNVHSAEggFNMIIBSTAIBgZngQwBAgEwggE7BgsrBgEEAYG1NwECAzCCASow
 | 
					 | 
				
			||||||
LgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYw
 | 
					 | 
				
			||||||
gfcGCCsGAQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9y
 | 
					 | 
				
			||||||
aXR5MAMCAQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3JkaW5n
 | 
					 | 
				
			||||||
IHRvIHRoZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRoZSBT
 | 
					 | 
				
			||||||
dGFydENvbSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRl
 | 
					 | 
				
			||||||
ZCBwdXJwb3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkgb2Js
 | 
					 | 
				
			||||||
aWdhdGlvbnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wu
 | 
					 | 
				
			||||||
Y29tL2NydDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcwAYYt
 | 
					 | 
				
			||||||
aHR0cDovL29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczEvc2VydmVyL2NhMEIG
 | 
					 | 
				
			||||||
CCsGAQUFBzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xh
 | 
					 | 
				
			||||||
c3MxLnNlcnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFydHNz
 | 
					 | 
				
			||||||
bC5jb20vMA0GCSqGSIb3DQEBBQUAA4IBAQCTTSbioYG8QJfK6Yfc3ijdS2oOh8AI
 | 
					 | 
				
			||||||
Gf3IN1TpmWAM8ijhDsDX0E8/Us6PHCwsg+yLuHI+92/MtHHSMnfew5HenTol6hNY
 | 
					 | 
				
			||||||
CDPnaHd1UtDfp6/yp8U0iQMWIjxecL46IAyjdD9tX43dLhL5fziQYEJ2rjFHtK8J
 | 
					 | 
				
			||||||
FBRg9QZI536BJ4aPfcFWwWtaYqWB7Nib1n86SKCPl0Tn1HfFJ+j0vkh0EwoJ3y3z
 | 
					 | 
				
			||||||
8VbJNwI0DxYMUDN2burWvEzUfAtNh2c7vuHhY6q96kNTMmbed/1DPUWWVyXKYtVc
 | 
					 | 
				
			||||||
FC9Q+3yQ3JqCJ1XoV3OxiYzdQnNn8WQGsEx1pxD9D6mHYnffeOUlHqhB
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFRTCCBC2gAwIBAgIQCeu0vyc0EdwhoPpohoWSuzANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGDAWBgNVBAMTD3N0
 | 
				
			||||||
 | 
					YXRzLnp1bGlwLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANPQ
 | 
				
			||||||
 | 
					XZXfNdVW7N6CSzpM74dtLMAawINFfYuk1VFUqzC5L5uP7ZUwvhYVKVlJrnd5afGp
 | 
				
			||||||
 | 
					XARqaYhddvJxbDihO3vgCopkHdcRikRrJgwSvLUtCeX8kLUyHTX6XXmn52CspX+r
 | 
				
			||||||
 | 
					s2OYecGna+dnscWyL3K1UlVISJ2lyKGZU6t72Fyt7XYIFzVd/VruK6jfWsbZOpZ6
 | 
				
			||||||
 | 
					HZgKzcYP1CTrsAg5LvW4dqNaEJya9+JdyRWJ9zgDSWV+XzsJtbY3hg8IrCNLB/ck
 | 
				
			||||||
 | 
					F7wElqQg/tJNELgUyQmrIhyxqgHu0Nsg56Ug2KhIby4QaBzgBy7U+oTRgM8SYVCN
 | 
				
			||||||
 | 
					iFM74FG1/DA08pERaBkCAwEAAaOCAd4wggHaMB8GA1UdIwQYMBaAFFFo/5CvAgd1
 | 
				
			||||||
 | 
					PMzZZWRiohK4WXI7MB0GA1UdDgQWBBQRkQ0SirqkXztkBjr55UekEAqdljAaBgNV
 | 
				
			||||||
 | 
					HREEEzARgg9zdGF0cy56dWxpcC5uZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
 | 
				
			||||||
 | 
					MBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8v
 | 
				
			||||||
 | 
					Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMDSgMqAwhi5o
 | 
				
			||||||
 | 
					dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMEIG
 | 
				
			||||||
 | 
					A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYY
 | 
				
			||||||
 | 
					aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2Fj
 | 
				
			||||||
 | 
					ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZl
 | 
				
			||||||
 | 
					ckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQArykRu8hdK
 | 
				
			||||||
 | 
					9tFLzDUcApS9xGuOSjJgGOPRW8symfNq4pU8dPp+gXtZ2BlxLeKn2bLR4XeLlvCj
 | 
				
			||||||
 | 
					LZRZaMVfrGyaEV9WzkyTVG64l7zjKNHqdN/AY/YAp6HcxXDNJs1eFUOB45yHLfkH
 | 
				
			||||||
 | 
					pG0gx9dnCR+rRyDpOVODNLP6/JIq79xluk6Eb4VaSlHrxnDoDb18Yolx3OlYnwNF
 | 
				
			||||||
 | 
					cceJrPJEL1AX7NqBRav7dSfR4DsyYzT+GKXx/mZe/igMn2pUjE5Idf5aw9citsU3
 | 
				
			||||||
 | 
					SaltVJZ3Kp4KBx1xHF06HUA3eb50vghOeGmMVYAWQIZeYHRDcbAhrFW0W7SnJwFc
 | 
				
			||||||
 | 
					ZQHYMrD1uDAQ
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										31
									
								
								puppet/zulip_internal/files/certs/stats.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								puppet/zulip_internal/files/certs/stats.zulip.net.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFRTCCBC2gAwIBAgIQCeu0vyc0EdwhoPpohoWSuzANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxGDAWBgNVBAMTD3N0
 | 
				
			||||||
 | 
					YXRzLnp1bGlwLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANPQ
 | 
				
			||||||
 | 
					XZXfNdVW7N6CSzpM74dtLMAawINFfYuk1VFUqzC5L5uP7ZUwvhYVKVlJrnd5afGp
 | 
				
			||||||
 | 
					XARqaYhddvJxbDihO3vgCopkHdcRikRrJgwSvLUtCeX8kLUyHTX6XXmn52CspX+r
 | 
				
			||||||
 | 
					s2OYecGna+dnscWyL3K1UlVISJ2lyKGZU6t72Fyt7XYIFzVd/VruK6jfWsbZOpZ6
 | 
				
			||||||
 | 
					HZgKzcYP1CTrsAg5LvW4dqNaEJya9+JdyRWJ9zgDSWV+XzsJtbY3hg8IrCNLB/ck
 | 
				
			||||||
 | 
					F7wElqQg/tJNELgUyQmrIhyxqgHu0Nsg56Ug2KhIby4QaBzgBy7U+oTRgM8SYVCN
 | 
				
			||||||
 | 
					iFM74FG1/DA08pERaBkCAwEAAaOCAd4wggHaMB8GA1UdIwQYMBaAFFFo/5CvAgd1
 | 
				
			||||||
 | 
					PMzZZWRiohK4WXI7MB0GA1UdDgQWBBQRkQ0SirqkXztkBjr55UekEAqdljAaBgNV
 | 
				
			||||||
 | 
					HREEEzARgg9zdGF0cy56dWxpcC5uZXQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW
 | 
				
			||||||
 | 
					MBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8v
 | 
				
			||||||
 | 
					Y3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMDSgMqAwhi5o
 | 
				
			||||||
 | 
					dHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzIuY3JsMEIG
 | 
				
			||||||
 | 
					A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQcwAYYY
 | 
				
			||||||
 | 
					aHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2Fj
 | 
				
			||||||
 | 
					ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZl
 | 
				
			||||||
 | 
					ckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQArykRu8hdK
 | 
				
			||||||
 | 
					9tFLzDUcApS9xGuOSjJgGOPRW8symfNq4pU8dPp+gXtZ2BlxLeKn2bLR4XeLlvCj
 | 
				
			||||||
 | 
					LZRZaMVfrGyaEV9WzkyTVG64l7zjKNHqdN/AY/YAp6HcxXDNJs1eFUOB45yHLfkH
 | 
				
			||||||
 | 
					pG0gx9dnCR+rRyDpOVODNLP6/JIq79xluk6Eb4VaSlHrxnDoDb18Yolx3OlYnwNF
 | 
				
			||||||
 | 
					cceJrPJEL1AX7NqBRav7dSfR4DsyYzT+GKXx/mZe/igMn2pUjE5Idf5aw9citsU3
 | 
				
			||||||
 | 
					SaltVJZ3Kp4KBx1xHF06HUA3eb50vghOeGmMVYAWQIZeYHRDcbAhrFW0W7SnJwFc
 | 
				
			||||||
 | 
					ZQHYMrD1uDAQ
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -1,37 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIGeDCCBWCgAwIBAgIDCzx7MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
 | 
					 | 
				
			||||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
 | 
					 | 
				
			||||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
 | 
					 | 
				
			||||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwNzI3MjA0OTI2
 | 
					 | 
				
			||||||
WhcNMTQwNzI4MjAyMjU4WjCBizEZMBcGA1UEDRMQZXJIOUp3Y3NxcFB3T1pQdTEL
 | 
					 | 
				
			||||||
MAkGA1UEBhMCVVMxGTAXBgNVBAMTEHN0YXRzMS56dWxpcC5uZXQxRjBEBgkqhkiG
 | 
					 | 
				
			||||||
9w0BCQEWNzE5YmI4ZDJjYjkwNzRjZGRhODY0OWQzNDFkZDhlY2Q1LnByb3RlY3RA
 | 
					 | 
				
			||||||
d2hvaXNndWFyZC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDn
 | 
					 | 
				
			||||||
/nUFbsm89+Npxgq+B2jRqGvOnCPQ6QRgWj6ZQdZGuyOJ9JquSVc9YGgG/MGSa5hv
 | 
					 | 
				
			||||||
vzPxhC3NI0hH1nHypJtXbQS+UkI2tRSKdW89LVLcMJi2epqwlisBpobNIuMIQbsA
 | 
					 | 
				
			||||||
6HXY6qFI1r3WyRUZ3YggL4j35FEOW7pwx81fBFOgZaFu7b1PSjWyy1G0IrPalVaI
 | 
					 | 
				
			||||||
USsHu/pX1RxoTkcPlqG40pjVaQKHruJIaAQBBrW1r/QpDgan6PwiOSWrTJe/+WHU
 | 
					 | 
				
			||||||
xqlKO4WmPV70HRTZOFfMBQzO3PdR6a4RntjVbvvMycmCn6B0DKjDdnlP0iKAnlii
 | 
					 | 
				
			||||||
Lxiv/QO0MNkeX2l/l0H7AgMBAAGjggLgMIIC3DAJBgNVHRMEAjAAMAsGA1UdDwQE
 | 
					 | 
				
			||||||
AwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUPZ5uzgMNpTBQ5DBA
 | 
					 | 
				
			||||||
kipoNphC4uYwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUwJgYDVR0R
 | 
					 | 
				
			||||||
BB8wHYIQc3RhdHMxLnp1bGlwLm5ldIIJenVsaXAubmV0MIIBVgYDVR0gBIIBTTCC
 | 
					 | 
				
			||||||
AUkwCAYGZ4EMAQIBMIIBOwYLKwYBBAGBtTcBAgMwggEqMC4GCCsGAQUFBwIBFiJo
 | 
					 | 
				
			||||||
dHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMIH3BggrBgEFBQcCAjCB
 | 
					 | 
				
			||||||
6jAnFiBTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTADAgEBGoG+VGhp
 | 
					 | 
				
			||||||
cyBjZXJ0aWZpY2F0ZSB3YXMgaXNzdWVkIGFjY29yZGluZyB0byB0aGUgQ2xhc3Mg
 | 
					 | 
				
			||||||
MSBWYWxpZGF0aW9uIHJlcXVpcmVtZW50cyBvZiB0aGUgU3RhcnRDb20gQ0EgcG9s
 | 
					 | 
				
			||||||
aWN5LCByZWxpYW5jZSBvbmx5IGZvciB0aGUgaW50ZW5kZWQgcHVycG9zZSBpbiBj
 | 
					 | 
				
			||||||
b21wbGlhbmNlIG9mIHRoZSByZWx5aW5nIHBhcnR5IG9ibGlnYXRpb25zLjA1BgNV
 | 
					 | 
				
			||||||
HR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLnN0YXJ0c3NsLmNvbS9jcnQxLWNybC5j
 | 
					 | 
				
			||||||
cmwwgY4GCCsGAQUFBwEBBIGBMH8wOQYIKwYBBQUHMAGGLWh0dHA6Ly9vY3NwLnN0
 | 
					 | 
				
			||||||
YXJ0c3NsLmNvbS9zdWIvY2xhc3MxL3NlcnZlci9jYTBCBggrBgEFBQcwAoY2aHR0
 | 
					 | 
				
			||||||
cDovL2FpYS5zdGFydHNzbC5jb20vY2VydHMvc3ViLmNsYXNzMS5zZXJ2ZXIuY2Eu
 | 
					 | 
				
			||||||
Y3J0MCMGA1UdEgQcMBqGGGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tLzANBgkqhkiG
 | 
					 | 
				
			||||||
9w0BAQUFAAOCAQEApEbVfCf5LBHi7wFwtfraYMuf8TTZ6B41mBmN3wnavc2STtOd
 | 
					 | 
				
			||||||
+G9J3+oJeI6pwuNAHeY08EQZqAj8ijUnXPueeIziWISzFIaCQC8svHruxgR0nPUk
 | 
					 | 
				
			||||||
vSas89B74EhQ3gFpoEwnyi8rq59xVjluLkLmA93PGIk8c/02Z5NsW05k508kZwsm
 | 
					 | 
				
			||||||
Y1qtD1vAbhHQaTTzyc+8VK7SNtzIkjaIRcyEwE+J63q5uTisMIoJFnZJiUN2vQqg
 | 
					 | 
				
			||||||
I6sFnSNahB5WxEKsX5PF3tC7XLH6d5NmRL7kEaHS7U5QHUPLAPZEsYTcBHreAzEl
 | 
					 | 
				
			||||||
cBHkBWDioqskhYGkrBBE5RFWCtzUmVo86mxHYA==
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIFQzCCBCugAwIBAgIQD9VdZebVvG9+AG9yMOzijTANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
 | 
					MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFzAVBgNVBAMTDnRy
 | 
				
			||||||
 | 
					YWMuenVsaXAubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdeK
 | 
				
			||||||
 | 
					urQ+rI5ICqWM5KIcPrEprv281Vf9yuQRInk9mz7WdoscuPEIfCrnVj+wXG9L4Pco
 | 
				
			||||||
 | 
					u+BIDRCZ5/a0yfimS8U23zcieDNtZP4/HKpgwIkk4NkIZ/6u2muWzMe6AEjePKsd
 | 
				
			||||||
 | 
					EImJzcuTGoXJIY+z3I1HlzPUwLMSk4dHXPho4c/TJcJvNBp/MPbWCAvAKNq1Ehwj
 | 
				
			||||||
 | 
					GqtQjSYeUq1JJlF+jRZl8UvJANIObvMFuxGllw9H5IUCBIzRNpXxARpd4Fnz1Au0
 | 
				
			||||||
 | 
					m7bhBmNYIzXqQWqBZfU/qng118YjOYC+ZrcJqG1j1Rk0lrXhnq36LfC1OrefwjsZ
 | 
				
			||||||
 | 
					p6ly/U5F8oVvC8wlxQIDAQABo4IB3TCCAdkwHwYDVR0jBBgwFoAUUWj/kK8CB3U8
 | 
				
			||||||
 | 
					zNllZGKiErhZcjswHQYDVR0OBBYEFMi87D8ybP+KnZR3Lg788zRzn2CiMBkGA1Ud
 | 
				
			||||||
 | 
					EQQSMBCCDnRyYWMuenVsaXAubmV0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
 | 
				
			||||||
 | 
					BggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2Ny
 | 
				
			||||||
 | 
					bDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0
 | 
				
			||||||
 | 
					cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcyLmNybDBCBgNV
 | 
				
			||||||
 | 
					HSAEOzA5MDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
 | 
				
			||||||
 | 
					aWdpY2VydC5jb20vQ1BTMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0
 | 
				
			||||||
 | 
					dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2Vy
 | 
				
			||||||
 | 
					dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJD
 | 
				
			||||||
 | 
					QS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAQEK5QSNBYXCR
 | 
				
			||||||
 | 
					VVWJtJYU3ftiA1vlzkUvSBBC3McgLk+xPyLJEZspKJ6SEqenbNLi05heT2i7DNi4
 | 
				
			||||||
 | 
					ePJA9sQHBPUUYralS2be0CXym5Kj8+J9DRUXG829VLUs3ZLEwzCPTJC0gJ5Qm9r0
 | 
				
			||||||
 | 
					DMOgce059q62pgSxqHGq9PRnYLfsImanr1fWxonrA+tSxr+ACA77617uShRFtEe7
 | 
				
			||||||
 | 
					w7W9kaHG/rxNX4NyaA1dTPKJ/+R70k1UJWyiwnpW1aKzdwF1sN4FZx0PW3YW5Fww
 | 
				
			||||||
 | 
					JFO5LluyysXF/ccndhPBphF+KE0H7PdWUjQsQWq2qd6nLt1ZWmJaJsRK+YmbxSzE
 | 
				
			||||||
 | 
					ijy7IvLskw==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -1,36 +1,31 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
MIIGUDCCBTigAwIBAgIDC9HlMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
 | 
					MIIFQzCCBCugAwIBAgIQD9VdZebVvG9+AG9yMOzijTANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTMwOTA0MDAxNzUy
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTYwMDAwMDBaFw0xNjA0MjAxMjAwMDBa
 | 
				
			||||||
WhcNMTQwOTA1MDIzOTIzWjBmMRkwFwYDVQQNExBVRURrSjRETjlnOVRHSU9EMQsw
 | 
					MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
CQYDVQQGEwJVUzEXMBUGA1UEAxMOdHJhYy56dWxpcC5uZXQxIzAhBgkqhkiG9w0B
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFzAVBgNVBAMTDnRy
 | 
				
			||||||
CQEWFGhvc3RtYXN0ZXJAenVsaXAuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
 | 
					YWMuenVsaXAubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzdeK
 | 
				
			||||||
MIIBCgKCAQEAzTJPAx4P6DYswRvG+nlzozYqEQJ07YoUMFOW+Gl11uu+OTF7coAF
 | 
					urQ+rI5ICqWM5KIcPrEprv281Vf9yuQRInk9mz7WdoscuPEIfCrnVj+wXG9L4Pco
 | 
				
			||||||
fI6zbCyufA8z3vekSYst6DGvkPJVzSgPffJX6TUrfEGmWjZ1cGR9yYx4n894ZjD0
 | 
					u+BIDRCZ5/a0yfimS8U23zcieDNtZP4/HKpgwIkk4NkIZ/6u2muWzMe6AEjePKsd
 | 
				
			||||||
rQprnc5v0AU1dusYIzw/DwxoV0Ah6v+XW3ovlllAPkuzgDPgL4pLbvnRqMjuJZpb
 | 
					EImJzcuTGoXJIY+z3I1HlzPUwLMSk4dHXPho4c/TJcJvNBp/MPbWCAvAKNq1Ehwj
 | 
				
			||||||
RRL5L2WMP9ViS5BtZnwQaT9f36IOb+La62n5WuBUrcY8VqTALoZ0Mn1ePedwWfP1
 | 
					GqtQjSYeUq1JJlF+jRZl8UvJANIObvMFuxGllw9H5IUCBIzRNpXxARpd4Fnz1Au0
 | 
				
			||||||
ASpTBaoSIOXnX99bdyfcXAZ34SIVh4w2or6DiweRWPCLAGmf4zcX4JZuLRqodRzA
 | 
					m7bhBmNYIzXqQWqBZfU/qng118YjOYC+ZrcJqG1j1Rk0lrXhnq36LfC1OrefwjsZ
 | 
				
			||||||
Yp8Nb+e9fyECNQXh7d9eCGGnRQKvTbWQsQIDAQABo4IC3jCCAtowCQYDVR0TBAIw
 | 
					p6ly/U5F8oVvC8wlxQIDAQABo4IB3TCCAdkwHwYDVR0jBBgwFoAUUWj/kK8CB3U8
 | 
				
			||||||
ADALBgNVHQ8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0OBBYEFE+l
 | 
					zNllZGKiErhZcjswHQYDVR0OBBYEFMi87D8ybP+KnZR3Lg788zRzn2CiMBkGA1Ud
 | 
				
			||||||
z3QC+/II2yTMU2ySY1bk/shOMB8GA1UdIwQYMBaAFOtCNNCYsKuf9BtrCPfMZC7v
 | 
					EQQSMBCCDnRyYWMuenVsaXAubmV0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
 | 
				
			||||||
DixFMCQGA1UdEQQdMBuCDnRyYWMuenVsaXAubmV0ggl6dWxpcC5uZXQwggFWBgNV
 | 
					BggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYuaHR0cDovL2Ny
 | 
				
			||||||
HSAEggFNMIIBSTAIBgZngQwBAgEwggE7BgsrBgEEAYG1NwECAzCCASowLgYIKwYB
 | 
					bDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcyLmNybDA0oDKgMIYuaHR0
 | 
				
			||||||
BQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwgfcGCCsG
 | 
					cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcyLmNybDBCBgNV
 | 
				
			||||||
AQUFBwICMIHqMCcWIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MAMC
 | 
					HSAEOzA5MDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5k
 | 
				
			||||||
AQEagb5UaGlzIGNlcnRpZmljYXRlIHdhcyBpc3N1ZWQgYWNjb3JkaW5nIHRvIHRo
 | 
					aWdpY2VydC5jb20vQ1BTMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYBBQUHMAGGGGh0
 | 
				
			||||||
ZSBDbGFzcyAxIFZhbGlkYXRpb24gcmVxdWlyZW1lbnRzIG9mIHRoZSBTdGFydENv
 | 
					dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL2NhY2Vy
 | 
				
			||||||
bSBDQSBwb2xpY3ksIHJlbGlhbmNlIG9ubHkgZm9yIHRoZSBpbnRlbmRlZCBwdXJw
 | 
					dHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFuY2VTZXJ2ZXJD
 | 
				
			||||||
b3NlIGluIGNvbXBsaWFuY2Ugb2YgdGhlIHJlbHlpbmcgcGFydHkgb2JsaWdhdGlv
 | 
					QS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAQEK5QSNBYXCR
 | 
				
			||||||
bnMuMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwuc3RhcnRzc2wuY29tL2Ny
 | 
					VVWJtJYU3ftiA1vlzkUvSBBC3McgLk+xPyLJEZspKJ6SEqenbNLi05heT2i7DNi4
 | 
				
			||||||
dDEtY3JsLmNybDCBjgYIKwYBBQUHAQEEgYEwfzA5BggrBgEFBQcwAYYtaHR0cDov
 | 
					ePJA9sQHBPUUYralS2be0CXym5Kj8+J9DRUXG829VLUs3ZLEwzCPTJC0gJ5Qm9r0
 | 
				
			||||||
L29jc3Auc3RhcnRzc2wuY29tL3N1Yi9jbGFzczEvc2VydmVyL2NhMEIGCCsGAQUF
 | 
					DMOgce059q62pgSxqHGq9PRnYLfsImanr1fWxonrA+tSxr+ACA77617uShRFtEe7
 | 
				
			||||||
BzAChjZodHRwOi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9zdWIuY2xhc3MxLnNl
 | 
					w7W9kaHG/rxNX4NyaA1dTPKJ/+R70k1UJWyiwnpW1aKzdwF1sN4FZx0PW3YW5Fww
 | 
				
			||||||
cnZlci5jYS5jcnQwIwYDVR0SBBwwGoYYaHR0cDovL3d3dy5zdGFydHNzbC5jb20v
 | 
					JFO5LluyysXF/ccndhPBphF+KE0H7PdWUjQsQWq2qd6nLt1ZWmJaJsRK+YmbxSzE
 | 
				
			||||||
MA0GCSqGSIb3DQEBBQUAA4IBAQAesF3CsRJ0xYo6DMY4nK+pUdNvo36hnbmibMeI
 | 
					ijy7IvLskw==
 | 
				
			||||||
mm4likq/gLPIWTujD/nRmfanhDAf4s5N0KTC7Dg/cz4F3b79k8E84abxA5FOvyBj
 | 
					 | 
				
			||||||
bBqQWTAQk55N2sZYiZKsUC7Jg6gHT4A13pYCpO6YXog7Yu6MsNuH+1PSMe1bLy7f
 | 
					 | 
				
			||||||
n3zSU5KIN39x5DuHz50bG/1M/IM+7OUkexojZsDtIvjAvNcdQuEEQqsPXCSkksPp
 | 
					 | 
				
			||||||
Bq7qVB6XUKiTlbIPz41JkJS6uAHJ6/bScj/wcPGsxKVo9DxmThfJ4WPircObR0gD
 | 
					 | 
				
			||||||
keboaE9UsYvK25Zr32NHDSN0cj21TzuVHwVIioz6ct3xkZYb
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIF3DCCBMSgAwIBAgIQB/FzpmEZ29lq/NnM5SNypTANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTAwMDAwMDBaFw0xNzA0MTMxMjAwMDBa
 | 
				
			||||||
 | 
					MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFzAVBgNVBAMMDiou
 | 
				
			||||||
 | 
					aHVtYnVnaHEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mVr
 | 
				
			||||||
 | 
					lCy+dTQe5dc5dE0CoAlOtIgLfAcIbHvoqtXpo6M1fhdCCJG8THvsdqgzRAJGsvmp
 | 
				
			||||||
 | 
					cPkjd1ahz8cs0Awq/4E1yRYvwc4n0Uj7kVkLo/daZB3U+9YE9zRNz8m0C7+5MVx3
 | 
				
			||||||
 | 
					yNXrSzsueA5Z2AHU7rsWGU4bFn0HD19BS0SsL4T/5XuHdxD5rY357lN2oy4hSGQO
 | 
				
			||||||
 | 
					Pzr/JkxiZCqvcyT/lYT1K0Z0OUjZxzZWnCKemXXCEreN7jyYqatgS3YolYeCtfr3
 | 
				
			||||||
 | 
					1LToY05r4br08frt6HfoJ/b+0wT5vLtBStRBoYbrXQ8bJh+pNdK/CdmnoOchxBUB
 | 
				
			||||||
 | 
					s3klxcji0z2P/j4q8wIDAQABo4ICdjCCAnIwHwYDVR0jBBgwFoAUUWj/kK8CB3U8
 | 
				
			||||||
 | 
					zNllZGKiErhZcjswHQYDVR0OBBYEFAPpaDtaKOl1+zRnO2xhgDQq/SxWMIGxBgNV
 | 
				
			||||||
 | 
					HREEgakwgaaCDiouaHVtYnVnaHEuY29tggxodW1idWdocS5jb22CDSouZS56dWxp
 | 
				
			||||||
 | 
					cC5jb22CC2UuenVsaXAuY29tgg4qLnp1bGlwY2RuLm5ldIIMenVsaXBjZG4ubmV0
 | 
				
			||||||
 | 
					gg4qLnp1bGlwY2RuLmNvbYIMenVsaXBjZG4uY29tggsqLnp1bGlwLm5ldIIJenVs
 | 
				
			||||||
 | 
					aXAubmV0ggsqLnp1bGlwLmNvbYIJenVsaXAuY29tMA4GA1UdDwEB/wQEAwIFoDAd
 | 
				
			||||||
 | 
					BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYu
 | 
				
			||||||
 | 
					aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcxLmNybDA0
 | 
				
			||||||
 | 
					oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcx
 | 
				
			||||||
 | 
					LmNybDBCBgNVHSAEOzA5MDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRw
 | 
				
			||||||
 | 
					czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYB
 | 
				
			||||||
 | 
					BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0
 | 
				
			||||||
 | 
					cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFu
 | 
				
			||||||
 | 
					Y2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
 | 
				
			||||||
 | 
					UbdsR5JFf+lqTU9T4H9Qz0A0Vi7T+1B2+uPEpsarTULENCImoJHt4nsglQrFmqlv
 | 
				
			||||||
 | 
					P3xnV7QoMuz+Fn/TWDDGNWYc3HxepMRsSpRFfrnrq8eLFYFCbNk9EG41mMA+kmyM
 | 
				
			||||||
 | 
					O+7Tg5o8Vz935Mwa1vWP/EIsgEINvgYx83MFelcP3lpxoRO1JTtA4sweLjZuPvLk
 | 
				
			||||||
 | 
					66o2lQi9tOEU735ySGEO/tgzPBPCwadfRz2olT8riUJf1ddi+BCXqoMQOUaENmRi
 | 
				
			||||||
 | 
					nyJ3vS2cNrX47gE7kYFlogvLAFgLBvlBXbQ5rI7YdXsvXpY4hY6bcd2LRZ92i614
 | 
				
			||||||
 | 
					MEvDJULOZS5Q7WFH9xp7+Q==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
 | 
				
			||||||
 | 
					ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
 | 
				
			||||||
 | 
					MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
 | 
				
			||||||
 | 
					LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
 | 
				
			||||||
 | 
					YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
 | 
				
			||||||
 | 
					4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
 | 
				
			||||||
 | 
					Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
 | 
				
			||||||
 | 
					itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
 | 
				
			||||||
 | 
					4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
 | 
				
			||||||
 | 
					sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
 | 
				
			||||||
 | 
					bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
 | 
				
			||||||
 | 
					MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
 | 
				
			||||||
 | 
					NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
 | 
				
			||||||
 | 
					dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
 | 
				
			||||||
 | 
					L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
 | 
				
			||||||
 | 
					BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
 | 
				
			||||||
 | 
					UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
 | 
				
			||||||
 | 
					aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
 | 
				
			||||||
 | 
					aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
 | 
				
			||||||
 | 
					E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
 | 
				
			||||||
 | 
					/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
 | 
				
			||||||
 | 
					xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
 | 
				
			||||||
 | 
					0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
 | 
				
			||||||
 | 
					cPUeybQ=
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
							
								
								
									
										34
									
								
								puppet/zulip_internal/files/certs/wildcard-all.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								puppet/zulip_internal/files/certs/wildcard-all.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					-----BEGIN CERTIFICATE-----
 | 
				
			||||||
 | 
					MIIF3DCCBMSgAwIBAgIQB/FzpmEZ29lq/NnM5SNypTANBgkqhkiG9w0BAQsFADBw
 | 
				
			||||||
 | 
					MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
 | 
				
			||||||
 | 
					d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNz
 | 
				
			||||||
 | 
					dXJhbmNlIFNlcnZlciBDQTAeFw0xNDA0MTAwMDAwMDBaFw0xNzA0MTMxMjAwMDBa
 | 
				
			||||||
 | 
					MGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
 | 
				
			||||||
 | 
					YW4gRnJhbmNpc2NvMRUwEwYDVQQKEwxEcm9wYm94LCBJbmMxFzAVBgNVBAMMDiou
 | 
				
			||||||
 | 
					aHVtYnVnaHEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4mVr
 | 
				
			||||||
 | 
					lCy+dTQe5dc5dE0CoAlOtIgLfAcIbHvoqtXpo6M1fhdCCJG8THvsdqgzRAJGsvmp
 | 
				
			||||||
 | 
					cPkjd1ahz8cs0Awq/4E1yRYvwc4n0Uj7kVkLo/daZB3U+9YE9zRNz8m0C7+5MVx3
 | 
				
			||||||
 | 
					yNXrSzsueA5Z2AHU7rsWGU4bFn0HD19BS0SsL4T/5XuHdxD5rY357lN2oy4hSGQO
 | 
				
			||||||
 | 
					Pzr/JkxiZCqvcyT/lYT1K0Z0OUjZxzZWnCKemXXCEreN7jyYqatgS3YolYeCtfr3
 | 
				
			||||||
 | 
					1LToY05r4br08frt6HfoJ/b+0wT5vLtBStRBoYbrXQ8bJh+pNdK/CdmnoOchxBUB
 | 
				
			||||||
 | 
					s3klxcji0z2P/j4q8wIDAQABo4ICdjCCAnIwHwYDVR0jBBgwFoAUUWj/kK8CB3U8
 | 
				
			||||||
 | 
					zNllZGKiErhZcjswHQYDVR0OBBYEFAPpaDtaKOl1+zRnO2xhgDQq/SxWMIGxBgNV
 | 
				
			||||||
 | 
					HREEgakwgaaCDiouaHVtYnVnaHEuY29tggxodW1idWdocS5jb22CDSouZS56dWxp
 | 
				
			||||||
 | 
					cC5jb22CC2UuenVsaXAuY29tgg4qLnp1bGlwY2RuLm5ldIIMenVsaXBjZG4ubmV0
 | 
				
			||||||
 | 
					gg4qLnp1bGlwY2RuLmNvbYIMenVsaXBjZG4uY29tggsqLnp1bGlwLm5ldIIJenVs
 | 
				
			||||||
 | 
					aXAubmV0ggsqLnp1bGlwLmNvbYIJenVsaXAuY29tMA4GA1UdDwEB/wQEAwIFoDAd
 | 
				
			||||||
 | 
					BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdQYDVR0fBG4wbDA0oDKgMIYu
 | 
				
			||||||
 | 
					aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcxLmNybDA0
 | 
				
			||||||
 | 
					oDKgMIYuaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItaGEtc2VydmVyLWcx
 | 
				
			||||||
 | 
					LmNybDBCBgNVHSAEOzA5MDcGCWCGSAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRw
 | 
				
			||||||
 | 
					czovL3d3dy5kaWdpY2VydC5jb20vQ1BTMIGDBggrBgEFBQcBAQR3MHUwJAYIKwYB
 | 
				
			||||||
 | 
					BQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBNBggrBgEFBQcwAoZBaHR0
 | 
				
			||||||
 | 
					cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkhpZ2hBc3N1cmFu
 | 
				
			||||||
 | 
					Y2VTZXJ2ZXJDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEA
 | 
				
			||||||
 | 
					UbdsR5JFf+lqTU9T4H9Qz0A0Vi7T+1B2+uPEpsarTULENCImoJHt4nsglQrFmqlv
 | 
				
			||||||
 | 
					P3xnV7QoMuz+Fn/TWDDGNWYc3HxepMRsSpRFfrnrq8eLFYFCbNk9EG41mMA+kmyM
 | 
				
			||||||
 | 
					O+7Tg5o8Vz935Mwa1vWP/EIsgEINvgYx83MFelcP3lpxoRO1JTtA4sweLjZuPvLk
 | 
				
			||||||
 | 
					66o2lQi9tOEU735ySGEO/tgzPBPCwadfRz2olT8riUJf1ddi+BCXqoMQOUaENmRi
 | 
				
			||||||
 | 
					nyJ3vS2cNrX47gE7kYFlogvLAFgLBvlBXbQ5rI7YdXsvXpY4hY6bcd2LRZ92i614
 | 
				
			||||||
 | 
					MEvDJULOZS5Q7WFH9xp7+Q==
 | 
				
			||||||
 | 
					-----END CERTIFICATE-----
 | 
				
			||||||
@@ -1,84 +0,0 @@
 | 
				
			|||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIFGzCCBAOgAwIBAgIQJMWnZBA8pItLin6/RwqFKzANBgkqhkiG9w0BAQUFADBz
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
 | 
					 | 
				
			||||||
VQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEZMBcGA1UE
 | 
					 | 
				
			||||||
AxMQUG9zaXRpdmVTU0wgQ0EgMjAeFw0xNDAxMTcwMDAwMDBaFw0xNTAxMTcyMzU5
 | 
					 | 
				
			||||||
NTlaMGExITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UE
 | 
					 | 
				
			||||||
CxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMRkwFwYDVQQDExB3d3cuaHVtYnVn
 | 
					 | 
				
			||||||
aHEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvhrAmjW7Om0e
 | 
					 | 
				
			||||||
AgdDCdjQER9CTKF7AlRxwn09ePWq6WaAH/bOHJlIKnv6l5e43odR2+VLQEYXITTE
 | 
					 | 
				
			||||||
f6aBV/Q3e96k1XwxL7QElns6bBAAdyiUIiEo1Mi/McUQIIGH+QF7SdkM2h6EN7EJ
 | 
					 | 
				
			||||||
OuZVbmqweGkMBQfkrG3bVHQ0xwIJyd6fFc+HBY7rNp/xFvrXeXO+Fe2OpwI/8MPM
 | 
					 | 
				
			||||||
oEUXQL3xph2vOGRxLvsQiOXJ19O9OISREw379RC4Nue0ZoOaW8B304UhrOSlr+wE
 | 
					 | 
				
			||||||
KqS4PsDUQ/7OSztaOswdc06InXKvB2g9v4Ut6AEFIm8kkY4nkxxNSVNbnqo359IK
 | 
					 | 
				
			||||||
6wqaEo4KwwIDAQABo4IBuzCCAbcwHwYDVR0jBBgwFoAUmeRAX2sUXj4F2d3TY1T8
 | 
					 | 
				
			||||||
Yrj3AKwwHQYDVR0OBBYEFKcvpXO4MrbndGJweHXaZZhIJBHiMA4GA1UdDwEB/wQE
 | 
					 | 
				
			||||||
AwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
 | 
					 | 
				
			||||||
AjBQBgNVHSAESTBHMDsGCysGAQQBsjEBAgIHMCwwKgYIKwYBBQUHAgEWHmh0dHA6
 | 
					 | 
				
			||||||
Ly93d3cucG9zaXRpdmVzc2wuY29tL0NQUzAIBgZngQwBAgEwOwYDVR0fBDQwMjAw
 | 
					 | 
				
			||||||
oC6gLIYqaHR0cDovL2NybC5jb21vZG9jYS5jb20vUG9zaXRpdmVTU0xDQTIuY3Js
 | 
					 | 
				
			||||||
MGwGCCsGAQUFBwEBBGAwXjA2BggrBgEFBQcwAoYqaHR0cDovL2NydC5jb21vZG9j
 | 
					 | 
				
			||||||
YS5jb20vUG9zaXRpdmVTU0xDQTIuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
 | 
					 | 
				
			||||||
cC5jb21vZG9jYS5jb20wOwYDVR0RBDQwMoIQd3d3Lmh1bWJ1Z2hxLmNvbYIQYXBp
 | 
					 | 
				
			||||||
Lmh1bWJ1Z2hxLmNvbYIMaHVtYnVnaHEuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQBN
 | 
					 | 
				
			||||||
UcbNU/VgDwvQ9BsDL9RM3Nad/muUgc3VF9KF4n0AwzsOxjE1l3toGo9da4MBnUCG
 | 
					 | 
				
			||||||
2dYntzCGGcbosiqQZl+3UEk8ny+2fW8BhXG0/4uKRQrSYAQOFgH6fr2OQqW1qT6o
 | 
					 | 
				
			||||||
wi4leXLA+Et+bKvDUYRQ8f9rGgPYIogqkioUp4KDuZsx2EKoVkrVtaL8e4n+xDMz
 | 
					 | 
				
			||||||
/hEMRMicCtrbzWec0wZZp0MfDpwbhLkD7KA7lfSy3E9Cx+BkOu4kFsHYhYIpWCZV
 | 
					 | 
				
			||||||
cSsfHDPABm5xawMq6HVK4EPkkAN4aQnRi+min3CInSQ73SaDVnxAS12NXyPgorbY
 | 
					 | 
				
			||||||
gzgt5befNJuv0nyYLiJa
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIE5TCCA82gAwIBAgIQB28SRoFFnCjVSNaXxA4AGzANBgkqhkiG9w0BAQUFADBv
 | 
					 | 
				
			||||||
MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk
 | 
					 | 
				
			||||||
ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF
 | 
					 | 
				
			||||||
eHRlcm5hbCBDQSBSb290MB4XDTEyMDIxNjAwMDAwMFoXDTIwMDUzMDEwNDgzOFow
 | 
					 | 
				
			||||||
czELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
 | 
					 | 
				
			||||||
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxGTAXBgNV
 | 
					 | 
				
			||||||
BAMTEFBvc2l0aXZlU1NMIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
 | 
					 | 
				
			||||||
AoIBAQDo6jnjIqaqucQA0OeqZztDB71Pkuu8vgGjQK3g70QotdA6voBUF4V6a4Rs
 | 
					 | 
				
			||||||
NjbloyTi/igBkLzX3Q+5K05IdwVpr95XMLHo+xoD9jxbUx6hAUlocnPWMytDqTcy
 | 
					 | 
				
			||||||
Ug+uJ1YxMGCtyb1zLDnukNh1sCUhYHsqfwL9goUfdE+SNHNcHQCgsMDqmOK+ARRY
 | 
					 | 
				
			||||||
FygiinddUCXNmmym5QzlqyjDsiCJ8AckHpXCLsDl6ez2PRIHSD3SwyNWQezT3zVL
 | 
					 | 
				
			||||||
yOf2hgVSEEOajBd8i6q8eODwRTusgFX+KJPhChFo9FJXb/5IC1tdGmpnc5mCtJ5D
 | 
					 | 
				
			||||||
YD7HWyoSbhruyzmuwzWdqLxdsC/DAgMBAAGjggF3MIIBczAfBgNVHSMEGDAWgBSt
 | 
					 | 
				
			||||||
vZh6NLQm9/rEJlTvA73gJMtUGjAdBgNVHQ4EFgQUmeRAX2sUXj4F2d3TY1T8Yrj3
 | 
					 | 
				
			||||||
AKwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEQYDVR0gBAow
 | 
					 | 
				
			||||||
CDAGBgRVHSAAMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0
 | 
					 | 
				
			||||||
LmNvbS9BZGRUcnVzdEV4dGVybmFsQ0FSb290LmNybDCBswYIKwYBBQUHAQEEgaYw
 | 
					 | 
				
			||||||
gaMwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9BZGRUcnVz
 | 
					 | 
				
			||||||
dEV4dGVybmFsQ0FSb290LnA3YzA5BggrBgEFBQcwAoYtaHR0cDovL2NydC51c2Vy
 | 
					 | 
				
			||||||
dHJ1c3QuY29tL0FkZFRydXN0VVROU0dDQ0EuY3J0MCUGCCsGAQUFBzABhhlodHRw
 | 
					 | 
				
			||||||
Oi8vb2NzcC51c2VydHJ1c3QuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQCcNuNOrvGK
 | 
					 | 
				
			||||||
u2yXjI9LZ9Cf2ISqnyFfNaFbxCtjDei8d12nxDf9Sy2e6B1pocCEzNFti/OBy59L
 | 
					 | 
				
			||||||
dLBJKjHoN0DrH9mXoxoR1Sanbg+61b4s/bSRZNy+OxlQDXqV8wQTqbtHD4tc0azC
 | 
					 | 
				
			||||||
e3chUN1bq+70ptjUSlNrTa24yOfmUlhNQ0zCoiNPDsAgOa/fT0JbHtMJ9BgJWSrZ
 | 
					 | 
				
			||||||
6EoYvzL7+i1ki4fKWyvouAt+vhcSxwOCKa9Yr4WEXT0K3yNRw82vEL+AaXeRCk/l
 | 
					 | 
				
			||||||
uuGtm87fM04wO+mPZn+C+mv626PAcwDj1hKvTfIPWhRRH224hoFiB85ccsJP81cq
 | 
					 | 
				
			||||||
cdnUl4XmGFO3
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
-----BEGIN CERTIFICATE-----
 | 
					 | 
				
			||||||
MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
 | 
					 | 
				
			||||||
MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
 | 
					 | 
				
			||||||
IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
 | 
					 | 
				
			||||||
MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
 | 
					 | 
				
			||||||
FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
 | 
					 | 
				
			||||||
bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
 | 
					 | 
				
			||||||
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
 | 
					 | 
				
			||||||
H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
 | 
					 | 
				
			||||||
uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
 | 
					 | 
				
			||||||
mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
 | 
					 | 
				
			||||||
a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
 | 
					 | 
				
			||||||
E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
 | 
					 | 
				
			||||||
WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
 | 
					 | 
				
			||||||
VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
 | 
					 | 
				
			||||||
Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
 | 
					 | 
				
			||||||
cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
 | 
					 | 
				
			||||||
IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
 | 
					 | 
				
			||||||
AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
 | 
					 | 
				
			||||||
YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
 | 
					 | 
				
			||||||
6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
 | 
					 | 
				
			||||||
Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
 | 
					 | 
				
			||||||
c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
 | 
					 | 
				
			||||||
mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
 | 
					 | 
				
			||||||
-----END CERTIFICATE-----
 | 
					 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user