<commit_before>/*
 * Copyright (c) 2015-2016 Spotify AB
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package com.spotify.sdk.android.auth.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;

import com.spotify.sdk.android.auth.AuthorizationRequest;
import com.spotify.sdk.android.auth.LoginActivity;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static com.spotify.sdk.android.auth.IntentExtras.KEY_VERSION;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_CLIENT_ID;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_REDIRECT_URI;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_REQUESTED_SCOPES;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_RESPONSE_TYPE;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_STATE;

public class SpotifyNativeAuthUtil {

    /*
     * The version of the auth protocol. More info about this protocol in
     * {@link com.spotify.sdk.android.auth.IntentExtras}.
     */
    private static final int PROTOCOL_VERSION = 1;

    private static final String SPOTIFY_AUTH_ACTIVITY_ACTION = "com.spotify.sso.action.START_AUTH_FLOW";
    private static final String SPOTIFY_PACKAGE_NAME = "com.spotify.music";
    private static final String[] SPOTIFY_PACKAGE_SUFFIXES = new String[]{
            ".debug",
            ".canary",
            ".partners",
            ""
    };
    private static final String[] SPOTIFY_SIGNATURE_HASH = new String[] {
            "80abdd17dcc4cb3a33815d354355bf87c9378624",
            "88df4d670ed5e01fc7b3eff13b63258628ff5a00",
            "d834ae340d1e854c5f4092722f9788216d9221e5",
            "1cbedd9e7345f64649bad2b493a20d9eea955352",
            "4b3d76a2de89033ea830f476a1f815692938e33b",
    };


    private Activity mContextActivity;
    private AuthorizationRequest mRequest;

    public SpotifyNativeAuthUtil(Activity contextActivity, AuthorizationRequest request) {
        mContextActivity = contextActivity;
        mRequest = request;
    }

    public boolean startAuthActivity() {
        Intent intent = createAuthActivityIntent();
        if (intent == null) {
            return false;
        }
        intent.putExtra(KEY_VERSION, PROTOCOL_VERSION);

        intent.putExtra(KEY_CLIENT_ID, mRequest.getClientId());
        intent.putExtra(KEY_REDIRECT_URI, mRequest.getRedirectUri());
        intent.putExtra(KEY_RESPONSE_TYPE, mRequest.getResponseType());
        intent.putExtra(KEY_REQUESTED_SCOPES, mRequest.getScopes());
        intent.putExtra(KEY_STATE, mRequest.getState());

        try {
            mContextActivity.startActivityForResult(intent, LoginActivity.REQUEST_CODE);
        } catch (ActivityNotFoundException e) {
            return false;
        }
        return true;
    }

    private Intent createAuthActivityIntent() {
        Intent intent = null;
        for (String suffix : SPOTIFY_PACKAGE_SUFFIXES) {
            intent = tryResolveActivity(SPOTIFY_PACKAGE_NAME + suffix);
            if (intent != null) {
                break;
            }
        }
        return intent;
    }

    private Intent tryResolveActivity(String packageName) {

        Intent intent = new Intent(SPOTIFY_AUTH_ACTIVITY_ACTION);
        intent.setPackage(packageName);

        ComponentName componentName = intent.resolveActivity(mContextActivity.getPackageManager());

        if (componentName == null) {
            return null;
        }

        if (!validateSignature(componentName.getPackageName())) {
            return null;
        }

        return intent;
    }

    @SuppressLint("PackageManagerGetSignatures")
    private boolean validateSignature(String spotifyPackageName) {
        try {
            final PackageInfo packageInfo = mContextActivity.getPackageManager().getPackageInfo(spotifyPackageName, PackageManager.GET_SIGNATURES);
            if (packageInfo.signatures == null) {
                return false;
            }

            for (Signature signature : packageInfo.signatures) {
                final String signatureString = signature.toCharsString();
                final String sha1Signature = sha1Hash(signatureString);
                for (String s : SPOTIFY_SIGNATURE_HASH) {
                    if (s.equals(sha1Signature)) {
                        return true;<commit_msg>Whitelist Spotify upload key<commit_after>/*
 * Copyright (c) 2015-2016 Spotify AB
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.
 */

package com.spotify.sdk.android.auth.app;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;

import com.spotify.sdk.android.auth.AuthorizationRequest;
import com.spotify.sdk.android.auth.LoginActivity;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static com.spotify.sdk.android.auth.IntentExtras.KEY_VERSION;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_CLIENT_ID;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_REDIRECT_URI;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_REQUESTED_SCOPES;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_RESPONSE_TYPE;
import static com.spotify.sdk.android.auth.IntentExtras.KEY_STATE;

public class SpotifyNativeAuthUtil {

    /*
     * The version of the auth protocol. More info about this protocol in
     * {@link com.spotify.sdk.android.auth.IntentExtras}.
     */
    private static final int PROTOCOL_VERSION = 1;

    private static final String SPOTIFY_AUTH_ACTIVITY_ACTION = "com.spotify.sso.action.START_AUTH_FLOW";
    private static final String SPOTIFY_PACKAGE_NAME = "com.spotify.music";
    private static final String[] SPOTIFY_PACKAGE_SUFFIXES = new String[]{
            ".debug",
            ".canary",
            ".partners",
            ""
    };
    private static final String[] SPOTIFY_SIGNATURE_HASH = new String[] {
            "25a9b2d2745c098361edaa3b87936dc29a28e7f1",
            "<KEY>",
            "88df4d670ed5e01fc7b3eff13b63258628ff5a00",
            "d834ae340d1e854c5f4092722f9788216d9221e5",
            "1cbedd9e7345f64649bad2b493a20d9eea955352",
            "4b3d76a2de89033ea830f476a1f815692938e33b",
    };


    private Activity mContextActivity;
    private AuthorizationRequest mRequest;

    public SpotifyNativeAuthUtil(Activity contextActivity, AuthorizationRequest request) {
        mContextActivity = contextActivity;
        mRequest = request;
    }

    public boolean startAuthActivity() {
        Intent intent = createAuthActivityIntent();
        if (intent == null) {
            return false;
        }
        intent.putExtra(KEY_VERSION, PROTOCOL_VERSION);

        intent.putExtra(KEY_CLIENT_ID, mRequest.getClientId());
        intent.putExtra(KEY_REDIRECT_URI, mRequest.getRedirectUri());
        intent.putExtra(KEY_RESPONSE_TYPE, mRequest.getResponseType());
        intent.putExtra(KEY_REQUESTED_SCOPES, mRequest.getScopes());
        intent.putExtra(KEY_STATE, mRequest.getState());

        try {
            mContextActivity.startActivityForResult(intent, LoginActivity.REQUEST_CODE);
        } catch (ActivityNotFoundException e) {
            return false;
        }
        return true;
    }

    private Intent createAuthActivityIntent() {
        Intent intent = null;
        for (String suffix : SPOTIFY_PACKAGE_SUFFIXES) {
            intent = tryResolveActivity(SPOTIFY_PACKAGE_NAME + suffix);
            if (intent != null) {
                break;
            }
        }
        return intent;
    }

    private Intent tryResolveActivity(String packageName) {

        Intent intent = new Intent(SPOTIFY_AUTH_ACTIVITY_ACTION);
        intent.setPackage(packageName);

        ComponentName componentName = intent.resolveActivity(mContextActivity.getPackageManager());

        if (componentName == null) {
            return null;
        }

        if (!validateSignature(componentName.getPackageName())) {
            return null;
        }

        return intent;
    }

    @SuppressLint("PackageManagerGetSignatures")
    private boolean validateSignature(String spotifyPackageName) {
        try {
            final PackageInfo packageInfo = mContextActivity.getPackageManager().getPackageInfo(spotifyPackageName, PackageManager.GET_SIGNATURES);
            if (packageInfo.signatures == null) {
                return false;
            }

            for (Signature actualApkSignature : packageInfo.signatures) {
                final String signatureString = actualApkSignature.toCharsString();
                final String sha1Signature = sha1Hash(signatureString);
                for (String knownSpotifyHash : SPOTIFY_SIGNATURE_HASH) {
                    if (knownSpotifyHash.equals(sha1Signature)) {
                        return true;
{'fraction_non_alphanumeric': 0.0796941219826792, 'fraction_numerical': 0.027271052146674038, 'mean_word_length': 3.1415490270888973, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3144281', 'n_tokens_mistral': 3166, 'n_tokens_neox': 2994, 'n_words': 697}