Merge branch 'main' into avm99963-monorail

Merged commit 34d8229ae2b51fb1a15bd208e6fe6185c94f6266

GitOrigin-RevId: 7ee0917f93a577e475f8e09526dd144d245593f4
diff --git a/framework/servlet_helpers.py b/framework/servlet_helpers.py
index fddec26..4d4259c 100644
--- a/framework/servlet_helpers.py
+++ b/framework/servlet_helpers.py
@@ -1,7 +1,6 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file or at
-# https://developers.google.com/open-source/licenses/bsd
+# Copyright 2016 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
 
 """Helper functions used by the Monorail servlet base class."""
 from __future__ import print_function
@@ -22,7 +21,7 @@
 from framework import template_helpers
 from framework import urls
 from framework import xsrf
-from proto import project_pb2
+from mrproto import project_pb2
 
 from google.appengine.api import app_identity
 from google.appengine.api import modules
@@ -209,28 +208,37 @@
   return (mr.project and mr.project.access != project_pb2.ProjectAccess.ANYONE)
 
 
-def SafeCreateLoginURL(mr, continue_url=None):
+def SafeCreateLoginURL(mr):
   """Make a login URL w/ a detailed continue URL, otherwise use a short one."""
-  current_page_url = mr.current_page_url_encoded
+  current_url = mr.current_page_url_encoded
   if settings.local_mode:
-    current_page_url = mr.current_page_url
-  continue_url = continue_url or current_page_url
+    current_url = mr.current_page_url
   try:
     # Check the URL length
-    generated_login_url = users.create_login_url(continue_url)
+    generated_login_url = users.create_login_url(current_url)
   except users.RedirectTooLongError:
     if mr.project_name:
-      continue_url = '/p/%s' % mr.project_name
+      current_url = '/p/%s' % mr.project_name
     else:
-      continue_url = '/'
+      current_url = '/'
   if settings.local_mode:
     return generated_login_url
+
+  current_parts = urllib.parse.urlparse(current_url)
+  current_query = current_parts.query
+  # Double encode only the query so that it survives redirect parsing.
+  current_url = urllib.parse.urlunparse(
+      current_parts[:3] + ('', urllib.parse.quote_plus(current_query), ''))
   # URL to allow user to choose an account when >1 account is logged in.
-  redirect_url = (
-      'https://accounts.google.com/AccountChooser?continue='
-      'https://uc.appengine.google.com/_ah/conflogin%3Fcontinue%3D{}')
-  url = redirect_url.format(continue_url)
-  return url
+  second_redirect_url = 'https://uc.appengine.google.com/_ah/conflogin?'
+  second_redirect_query = 'continue=' + current_url
+  second_redirect_uri = second_redirect_url + second_redirect_query
+
+  first_redirect_url = 'https://accounts.google.com/AccountChooser?'
+  first_redirect_params = {'continue': second_redirect_uri}
+  first_redirect_uri = first_redirect_url + urllib.parse.urlencode(
+      first_redirect_params)
+  return first_redirect_uri
 
 
 def SafeCreateLogoutURL(mr):
@@ -275,6 +283,6 @@
       project_alert = (
           'Scheduled for deletion in %d %s.' % (delay_days, days_word))
   elif project.state == project_pb2.ProjectState.ARCHIVED:
-    project_alert = 'Project is archived: read-only by members only.'
+    project_alert = 'Project is archived and read-only.'
 
   return project_alert