@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at upstream/main 180 lines 5.3 kB view raw
1<?php 2 3/** 4 * Consolidates Phabricator application cookies, including registration 5 * and session management. 6 * 7 * @task clientid Client ID Cookie 8 * @task next Next URI Cookie 9 */ 10final class PhabricatorCookies extends Phobject { 11 12 /** 13 * Stores the login username for password authentication. This is just a 14 * display value for convenience, used to prefill the login form. It is not 15 * authoritative. 16 */ 17 const COOKIE_USERNAME = 'phusr'; 18 19 20 /** 21 * Stores the user's current session ID. This is authoritative and establishes 22 * the user's identity. 23 */ 24 const COOKIE_SESSION = 'phsid'; 25 26 27 /** 28 * Stores a secret used during new account registration to prevent an attacker 29 * from tricking a victim into registering an account which is linked to 30 * credentials the attacker controls. 31 */ 32 const COOKIE_REGISTRATION = 'phreg'; 33 34 35 /** 36 * Stores a secret used during OAuth2 handshakes to prevent various attacks 37 * where an attacker hands a victim a URI corresponding to the middle of an 38 * OAuth2 workflow and we might otherwise do something sketchy. Particularly, 39 * this corresponds to the OAuth2 "code". 40 */ 41 const COOKIE_CLIENTID = 'phcid'; 42 43 44 /** 45 * Stores the URI to redirect the user to after login. This allows users to 46 * visit a path like `/feed/`, be prompted to login, and then be redirected 47 * back to `/feed/` after the workflow completes. 48 */ 49 const COOKIE_NEXTURI = 'next_uri'; 50 51 52 /** 53 * Stores a hint that the user should be moved directly into high security 54 * after upgrading a partial login session. This is used during password 55 * recovery to avoid a double-prompt. 56 */ 57 const COOKIE_HISEC = 'jump_to_hisec'; 58 59 60 /** 61 * Stores an invite code. 62 */ 63 const COOKIE_INVITE = 'invite'; 64 65 66 /** 67 * Stores a workflow completion across a redirect-after-POST following a 68 * form submission. This can be used to show "Changes Saved" messages. 69 */ 70 const COOKIE_SUBMIT = 'phfrm'; 71 72 73/* -( Client ID Cookie )--------------------------------------------------- */ 74 75 76 /** 77 * Set the client ID cookie. This is a random cookie used like a CSRF value 78 * during authentication workflows. 79 * 80 * @param AphrontRequest $request Request to modify. 81 * @return void 82 * @task clientid 83 */ 84 public static function setClientIDCookie(AphrontRequest $request) { 85 86 // NOTE: See T3471 for some discussion. Some browsers and browser extensions 87 // can make duplicate requests, so we overwrite this cookie only if it is 88 // not present in the request. The cookie lifetime is limited by making it 89 // temporary and clearing it when users log out. 90 91 $value = $request->getCookie(self::COOKIE_CLIENTID); 92 if (!phutil_nonempty_string($value)) { 93 $request->setTemporaryCookie( 94 self::COOKIE_CLIENTID, 95 Filesystem::readRandomCharacters(16)); 96 } 97 } 98 99 100/* -( Next URI Cookie )---------------------------------------------------- */ 101 102 103 /** 104 * Set the Next URI cookie. We only write the cookie if it wasn't recently 105 * written, to avoid writing over a real URI with a bunch of "humans.txt" 106 * stuff. See T3793 for discussion. 107 * 108 * @param AphrontRequest $request Request to write to. 109 * @param string $next_uri URI to write. 110 * @param bool $force (optional) Write this cookie even if we 111 * have a fresh cookie already. 112 * @return void 113 * 114 * @task next 115 */ 116 public static function setNextURICookie( 117 AphrontRequest $request, 118 $next_uri, 119 $force = false) { 120 121 if (!$force) { 122 $cookie_value = $request->getCookie(self::COOKIE_NEXTURI); 123 list($set_at, $current_uri) = self::parseNextURICookie($cookie_value); 124 125 // If the cookie was set within the last 2 minutes, don't overwrite it. 126 // Primarily, this prevents browser requests for resources which do not 127 // exist (like "humans.txt" and various icons) from overwriting a normal 128 // URI like "/feed/". 129 if ($set_at > (time() - 120)) { 130 return; 131 } 132 } 133 134 $new_value = time().','.$next_uri; 135 $request->setTemporaryCookie(self::COOKIE_NEXTURI, $new_value); 136 } 137 138 139 /** 140 * Read the URI out of the Next URI cookie. 141 * 142 * @param AphrontRequest $request Request to examine. 143 * @return string|null Next URI cookie's URI value. 144 * 145 * @task next 146 */ 147 public static function getNextURICookie(AphrontRequest $request) { 148 $cookie_value = $request->getCookie(self::COOKIE_NEXTURI); 149 list($set_at, $next_uri) = self::parseNextURICookie($cookie_value); 150 151 return $next_uri; 152 } 153 154 155 /** 156 * Parse a Next URI cookie into its components. 157 * 158 * @param string $cookie Raw cookie value. 159 * @return list<int,string>|null List of timestamp and URI, or null if the 160 * cookie is empty or null. 161 * 162 * @task next 163 */ 164 private static function parseNextURICookie($cookie) { 165 // Old cookies look like: /uri 166 // New cookies look like: timestamp,/uri 167 168 if (!phutil_nonempty_string($cookie)) { 169 return null; 170 } 171 172 if (strpos($cookie, ',') !== false) { 173 list($timestamp, $uri) = explode(',', $cookie, 2); 174 return array((int)$timestamp, $uri); 175 } 176 177 return array(0, $cookie); 178 } 179 180}