content: /*
      Android Asynchronous Http Client Sample
      Copyright (c) 2014 Marek Sebera <marek.sebera@gmail.com>
      https://github.com/android-async-http/android-async-http
  
      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
  
          https://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.
  */
  
  package com.loopj.android.http.sample;
  
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.View;
  import android.widget.EditText;
  import android.widget.LinearLayout;
  import android.widget.TextView;
  
  import com.fasterxml.jackson.core.JsonFactory;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.loopj.android.http.AsyncHttpClient;
  import com.loopj.android.http.Base64;
  import com.loopj.android.http.BaseJsonHttpResponseHandler;
  import com.loopj.android.http.RequestHandle;
  import com.loopj.android.http.ResponseHandlerInterface;
  import com.loopj.android.http.sample.util.SampleJSON;
  
  import java.util.List;
  import java.util.Locale;
  
  import cz.msebera.android.httpclient.Header;
  import cz.msebera.android.httpclient.HttpEntity;
  import cz.msebera.android.httpclient.message.BasicHeader;
  
  /**
   * This sample demonstrates how to implement HTTP 401 Basic Authentication.
   *
   * @author Noor Dawod <github@fineswap.com>
   */
  public class Http401AuthSample extends GetSample {
  
      private static final String LOG_TAG = "Http401AuthSample";
      private static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
      private static final String HEADER_AUTHORIZATION = "Authorization";
      private static final String HEADER_REALM_PREFIX = "realm=";
      private static final String HEADER_BASIC = "basic";
  
      private static final String SECRET_USERNAME = "ahc";
      private static final String SECRET_PASSWORD = "LetMeIn";
  
      private String userName;
      private String passWord;
  
      public void retryRequest() {
          // File is still smaller than remote file; send a new request.
          onRunButtonPressed();
      }
  
      @Override
      public String getDefaultURL() {
          return PROTOCOL + "httpbin.org/basic-auth/" + SECRET_USERNAME + "/" + SECRET_PASSWORD;
      }
  
      @Override
      public int getSampleTitle() {
          return R.string.title_401_unauth;
      }
  
      @Override
      public RequestHandle executeSample(AsyncHttpClient client, String URL, Header[] headers, HttpEntity entity, ResponseHandlerInterface responseHandler) {
          return client.get(this, URL, headers, null, responseHandler);
      }
  
      @Override
      public Header[] getRequestHeaders() {
          List<Header> headers = getRequestHeadersList();
  
          // Add authentication header.
          if (userName != null && passWord != null) {
              byte[] base64bytes = Base64.encode(
                      (userName + ":" + passWord).getBytes(),
                      Base64.DEFAULT
              );
              String credentials = new String(base64bytes);
              headers.add(new BasicHeader(HEADER_AUTHORIZATION, HEADER_BASIC + " " + credentials));
          }
  
          return headers.toArray(new Header[headers.size()]);
      }
  
      @Override
      public ResponseHandlerInterface getResponseHandler() {
          return new BaseJsonHttpResponseHandler<SampleJSON>() {
  
              @Override
              public void onStart() {
                  clearOutputs();
              }
  
              @Override
              public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, SampleJSON response) {
                  debugHeaders(LOG_TAG, headers);
                  debugStatusCode(LOG_TAG, statusCode);
                  if (response != null) {
                      debugResponse(LOG_TAG, rawJsonResponse);
                  }
              }
  
              @Override
              public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, SampleJSON errorResponse) {
                  debugHeaders(LOG_TAG, headers);
                  debugStatusCode(LOG_TAG, statusCode);
                  debugThrowable(LOG_TAG, throwable);
  
                  // Ask the user for credentials if required by the server.
                  if (statusCode == 401) {
                      String realm = "Protected Page";
                      String authType = null;
  
                      // Cycle through the headers and look for the WWW-Authenticate header.
                      for (Header header : headers) {
                          String headerName = header.getName();
                          if (HEADER_WWW_AUTHENTICATE.equalsIgnoreCase(headerName)) {
                              String headerValue = header.getValue().trim();
                              String headerValueLowerCase = headerValue.toLowerCase(Locale.US);
  
                              // Get the type of auth requested.
                              int charPos = headerValueLowerCase.indexOf(' ');
                              if (0 < charPos) {
                                  authType = headerValueLowerCase.substring(0, charPos);
  
                                  // The second part should begin with a "realm=" prefix.
                                  if (headerValueLowerCase.substring(1 + charPos).startsWith(HEADER_REALM_PREFIX)) {
                                      // The new realm value, including any possible wrapping quotation.
                                      realm = headerValue.substring(1 + charPos + HEADER_REALM_PREFIX.length());
  
                                      // If realm starts with a quote, remove surrounding quotes.
                                      if (realm.charAt(0) == '"' || realm.charAt(0) == '\'') {
                                          realm = realm.substring(1, realm.length() - 1);
                                      }
                                  }
                              }
                          }
                      }
  
                      // We will support basic auth in this sample.
                      if (authType != null && HEADER_BASIC.equals(authType)) {
                          // Show a dialog for the user and request user/pass.
                          Log.d(LOG_TAG, HEADER_REALM_PREFIX + realm);
  
                          // Present the dialog.
                          postRunnable(new DialogRunnable(realm));
                      }
                  }
              }
  
              @Override
              protected SampleJSON parseResponse(String rawJsonData, boolean isFailure) throws Throwable {
                  return new ObjectMapper().readValues(new JsonFactory().createParser(rawJsonData), SampleJSON.class).next();
              }
          };
      }
  
      private class DialogRunnable implements Runnable, DialogInterface.OnClickListener {
  
          final String realm;
          final View dialogView;
  
          public DialogRunnable(String realm) {
              this.realm = realm;
              this.dialogView = LayoutInflater
                      .from(Http401AuthSample.this)
                      .inflate(R.layout.credentials, new LinearLayout(Http401AuthSample.this), false);
  
              // Update the preface text with correct credentials.
              TextView preface = (TextView) dialogView.findViewById(R.id.label_credentials);
              String prefaceText = preface.getText().toString();
  
              // Substitute placeholders, and re-set the value.
              preface.setText(String.format(Locale.US, prefaceText, SECRET_USERNAME, SECRET_PASSWORD));
          }
  
          @Override
          public void run() {
              AlertDialog.Builder builder = new AlertDialog.Builder(Http401AuthSample.this);
              builder.setTitle(realm);
              builder.setView(dialogView);
              builder.setPositiveButton(android.R.string.ok, this);
              builder.setNegativeButton(android.R.string.cancel, this);
              builder.show();
          }
  
          @Override
          public void onClick(DialogInterface dialog, int which) {
              switch (which) {
                  case DialogInterface.BUTTON_POSITIVE:
                      // Dismiss the dialog.
                      dialog.dismiss();
  
                      // Update the username and password variables.
                      userName = ((EditText) dialogView.findViewById(R.id.field_username)).getText().toString();
                      passWord = ((EditText) dialogView.findViewById(R.id.field_password)).getText().toString();
  
                      // Refetch the remote file.
                      retryRequest();
  
                      break;
  
                  case DialogInterface.BUTTON_NEGATIVE:
                      // Dismiss the dialog.
                      dialog.dismiss();
  
                      break;
              }
          }
      }
  }
  