Android Open Source - PlayMusicExporter All Access Exporter






From Project

Back to project page PlayMusicExporter.

License

The source code is released under:

Copyright (c) 2015 David Schulte 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 Soft...

If you think the Android project PlayMusicExporter listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (c) 2015 David Schulte/*w w  w  . ja v  a2s .c o m*/
 *
 * 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.
 */

package de.arcus.playmusiclib;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * Exports encrypted music files from Google Music All Access
 */
public class AllAccessExporter {
    private Cipher mCipher;
    private SecretKeySpec mKeySpec;
    private InputStream mInput;
    private OutputStream mOutput;
    private byte[] mMagicNumber;

    static final int BUFFER_SIZE = 1024;
    static final byte[] MAGIC_NUMBER = { 18, -45, 21, 39 };

    /**
     * Creates a new exporter for AllAccess files
     *
     * @param input The encrypted music file (Copy the file into a readable directory before you use them.)
     * @param cpData The 16 byte long key (CpData-Blob in MUSIC table)
     * @throws NoSuchAlgorithmException Encryption method is not supported on this device
     * @throws NoSuchPaddingException Padding mode is not supported on this device
     * @throws IOException File could not be read (This class does not support SU commands; first copy your file into a readable directory)
     */
    public AllAccessExporter(String input, byte[] cpData) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException
    {
        // Select encryption mode
        mCipher = Cipher.getInstance("AES/CTR/NoPadding");
        mKeySpec = new SecretKeySpec(cpData, "AES");

        // Opens the source file
        mInput = new FileInputStream(input);

        // Reads the first 4 bytes = MagicNumber
        mMagicNumber = new byte[4];
        if (mInput.read(mMagicNumber) != 4)
            mMagicNumber = null;
    }

    /**
     * Checks whether the magic number of the file is correct
     *
     * @return Returns whether the Magic Number is valid
     */
    public boolean hasValidMagicNumber()
    {
        if (mMagicNumber == null)
            return false;

        if (mMagicNumber.length != 4)
            return false;

        for(int i=0; i<4; i++)
            if (mMagicNumber[i] != MAGIC_NUMBER[i])
                return false;

        return true;
    }

    /**
     * Saves an unencrypted copy of the music file as an Mp3
     * @param filename The path to the target file
     * @return Returns whether the file was successfully saved
     */
    public boolean save(String filename)
    {
        try {
            // Opens the target file
            mOutput = new FileOutputStream(filename);

            byte[] output = new byte[BUFFER_SIZE];

            // Reads all blocks of the file
            while(mInput.available() > 0) {
                int size = read(output);
                if (size > 0) {
                    mOutput.write(output, 0, size);
                } else
                    break;
            }

            // Close the files
            mInput.close();
            mOutput.close();

            // Everything went according to plan
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Try to close the files if an error occurs
        try {
            if (mInput != null)
                mInput.close();
            if (mOutput != null)
                mOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // An error has Occurred
        return false;
    }

    /**
     * Reads a block and decrypts it
     * @param output output buffer
     * @return Returns the length of the output buffer
     * @throws Exception
     */
    private int read(byte[] output) throws Exception
    {
        byte[] mBuffer = new byte[BUFFER_SIZE];
        byte[] mIvBuffer = new byte[16];

        int pos = 0;

        // Fills the buffer
        while (pos < BUFFER_SIZE)
        {
            int size = mInput.read(mBuffer, pos, BUFFER_SIZE - pos);
            // There is nothing more to read
            if (size == -1)
            {
                // Error, there was nothing more to read
                if (pos == 0)
                    return -1;

                // Buffer is filled
                if (pos > 16)
                    break;

                // Error, block is smaller than 16 bytes
                return -1;
            }
            pos += size;
        }

        // The first 16 bytes of the block are the initialization vector
        System.arraycopy(mBuffer, 0, mIvBuffer, 0, 16);
        IvParameterSpec ivParameter = new IvParameterSpec(mIvBuffer);

        // The remaining bytes are the encrypted data
        int decodeSize = pos - 16;

        try
        {
            // Initializes the encryption method
            mCipher.init(Cipher.DECRYPT_MODE, mKeySpec, ivParameter);

            // Decrypts the block
            if (mCipher.doFinal(mBuffer, 16, decodeSize, output, 0) != decodeSize)
                throw new IllegalStateException("Wrong block size");
        }
        catch (Exception ex)
        {
            // Unexpected error
            throw new Exception("Unexpected error while decrypting", ex);
        }

        // Returns the block size
        return decodeSize;
    }
}




Java Source Code List

de.arcus.framework.ApplicationTest.java
de.arcus.framework.crashhandler.CrashActivity.java
de.arcus.framework.crashhandler.CrashHandler.java
de.arcus.framework.logger.Logger.java
de.arcus.framework.settings.AppSettings.java
de.arcus.framework.superuser.SuperUserCommandCallback.java
de.arcus.framework.superuser.SuperUserCommand.java
de.arcus.framework.superuser.SuperUserTools.java
de.arcus.framework.superuser.SuperUser.java
de.arcus.framework.utils.FileTools.java
de.arcus.framework.utils.MediaScanner.java
de.arcus.playmusicexporter2.ApplicationTest.java
de.arcus.playmusicexporter2.activitys.MusicTrackDetailActivity.java
de.arcus.playmusicexporter2.activitys.MusicTrackListActivity.java
de.arcus.playmusicexporter2.adapter.MusicTrackAdapter.java
de.arcus.playmusicexporter2.adapter.MusicTrackListAdapter.java
de.arcus.playmusicexporter2.fragments.MusicTrackDetailFragment.java
de.arcus.playmusicexporter2.fragments.MusicTrackListFragment.java
de.arcus.playmusicexporter2.fragments.NavigationDrawerFragment.java
de.arcus.playmusicexporter2.utils.ImageViewLoader.java
de.arcus.playmusicexporter2.utils.MusicPathBuilder.java
de.arcus.playmusiclib.AllAccessExporter.java
de.arcus.playmusiclib.ApplicationTest.java
de.arcus.playmusiclib.PlayMusicManager.java
de.arcus.playmusiclib.datasources.AlbumDataSource.java
de.arcus.playmusiclib.datasources.ArtistDataSource.java
de.arcus.playmusiclib.datasources.DataSource.java
de.arcus.playmusiclib.datasources.MusicTrackDataSource.java
de.arcus.playmusiclib.datasources.PlaylistDataSource.java
de.arcus.playmusiclib.enums.ID3v2Version.java
de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException.java
de.arcus.playmusiclib.exceptions.NoSuperUserException.java
de.arcus.playmusiclib.exceptions.PlayMusicNotFoundException.java
de.arcus.playmusiclib.items.Album.java
de.arcus.playmusiclib.items.Artist.java
de.arcus.playmusiclib.items.MusicTrackList.java
de.arcus.playmusiclib.items.MusicTrack.java
de.arcus.playmusiclib.items.Playlist.java