net.fizzl.redditengine.impl.AccountApi.java Source code

Java tutorial

Introduction

Here is the source code for net.fizzl.redditengine.impl.AccountApi.java

Source

    /**
    /**
     * Copyright Maxpower Inc Finland (2014)
     *
     * This file is part of RedditEngine.
     *
     * RedditEngine is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     *
     * RedditEngine is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU Lesser General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public License
     * along with RedditEngine.  If not, see <http://www.gnu.org/licenses/>.
     **/
    *Copyright Maxpower Inc Finland(2014)**This file is part of RedditEngine.**RedditEngine is free software:you can redistribute it and/or modify*it under the terms of the GNU Lesser General Public License as published by*the Free Software Foundation,either version 3 of the License,or*(at your option)any later version.**RedditEngine is distributed in the hope that it will be useful,*but WITHOUT ANY WARRANTY;without even the implied warranty of*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the*GNU Lesser General Public License for more details.**You should have received a copy of the GNU Lesser General Public License*along with RedditEngine.If not,see<http://www.gnu.org/licenses/>.
    **//**
    *Copyright Maxpower Inc Finland(2014)**This file is part of RedditEngine.**RedditEngine is free software:you can redistribute it and/or modify*it under the terms of the GNU Lesser General Public License as published by*the Free Software Foundation,either version 3 of the License,or*(at your option)any later version.**RedditEngine is distributed in the hope that it will be useful,*but WITHOUT ANY WARRANTY;without even the implied warranty of*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the*GNU Lesser General Public License for more details.**You should have received a copy of the GNU Lesser General Public License*along with RedditEngine.If not,see<http://www.gnu.org/licenses/>.
    **/

package net.fizzl.redditengine.impl;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
    import org.apache.http.message.BasicNameValuePair;

    import android.util.Log;
    import net.fizzl.redditengine.data.AuthResponse;
    import net.fizzl.redditengine.data.GsonTemplate;
    import net.fizzl.redditengine.data.JsonResponse;
    import net.fizzl.redditengine.data.User;

    public class AccountApi extends BaseApi {
        private static final String LOGIN_PATH = "/api/login";
        private static final String API_TYPE_JSON = "json";

        /**
         * Clear all session cookies and replace the current one.
         * 
         * @param passwd   the user's current password
         * @return         errors if unsuccessful
         * @throws RedditEngineException
         */
        public JsonResponse<?> clearSessions(String passwd) throws RedditEngineException {
            StringBuilder path = new StringBuilder();
            path.append(UrlUtils.REDDIT_SSL);
            path.append("/api/clear_sessions");
            String url = path.toString();

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("api_type", API_TYPE_JSON));

            if (passwd != null && !passwd.isEmpty()) {
                params.add(new BasicNameValuePair("curpass", passwd));
            } else if (lastPassword != null) {
                params.add(new BasicNameValuePair("curpass", lastPassword));
            }
            // TODO destination url parameter "dest"
            // TODO should manually clear session cookies?

            JsonResponse<?> response = new AuthResponse(); // AuthResponse is a temporary placeholder to get data into JsonReponse. TODO should not depend on AuthResponse
            try {
                SimpleHttpClient client = SimpleHttpClient.getInstance();
                InputStream is = client.post(url, params);
                response = AuthResponse.fromInputStream(is);
                Log.d(getClass().getName(), new com.google.gson.Gson().toJson(response));
                is.close();
            } catch (Exception e) {
                RedditEngineException re = new RedditEngineException(e);
                throw re;
            }
            return response;
        }

        /**
         * Delete the currently logged in account.
         * 
         * @param user      a username
         * @param passwd   the user's password
         * @param message   a string no longer than 500 characters
         * @return {@link JsonResponse}
         * @throws RedditEngineException
         */
        public JsonResponse<?> deleteUser(String user, String passwd, String message) throws RedditEngineException {
            StringBuilder path = new StringBuilder();
            path.append(UrlUtils.REDDIT_SSL);
            path.append("/api/delete_user");
            String url = path.toString();

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("api_type", API_TYPE_JSON));
            params.add(new BasicNameValuePair("user", user));
            if (passwd != null) {
                params.add(new BasicNameValuePair("passwd", passwd));
            }
            if (message != null) {
                params.add(new BasicNameValuePair("delete_message", message));
            }
            params.add(new BasicNameValuePair("confirm", String.valueOf(true)));

            // possible responses:
            // {"json": {"errors": [["USER_REQUIRED", "please login to do that", null]]}}
            // {"json": {"errors": []}}
            JsonResponse<?> retval;
            try {
                SimpleHttpClient client = SimpleHttpClient.getInstance();
                InputStream is = client.post(url, params);
                retval = GsonTemplate.fromInputStream(is, JsonResponse.class);
                is.close();
            } catch (Exception e) {
                throw new RedditEngineException(e);
            }

            return retval;
        }

        /**
         * Log into a reddit account using SSL
         * 
         * @param user      username
         * @param passwd   users password
         * @param remember   specifies whether or not the session cookie returned should last beyond the current browser session 
         * @throws RedditEngineException
         */
        public AuthResponse login(String user, String passwd, boolean remember) throws RedditEngineException {
            StringBuilder sb = new StringBuilder();
            sb.append(UrlUtils.REDDIT_SSL);
            sb.append(LOGIN_PATH);
            String url = sb.toString();

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("user", user));
            params.add(new BasicNameValuePair("passwd", passwd));
            params.add(new BasicNameValuePair("api_type", API_TYPE_JSON));
            params.add(new BasicNameValuePair("rem", Boolean.toString(remember)));

            // The HTTP status code of the response will almost always be a 200 (OK) regardless of authentication success.
            // To see if login was successful, check the JSON response.
            // POST requests to /api/login must not include a reddit_session cookie along in the request. If a reddit_session cookie exists, the request may fail with a 409 status.

            AuthResponse ret = null;
            SimpleHttpClient client = SimpleHttpClient.getInstance();
            // TODO should SimpleHttpClient have some kind of save/restore cookies function instead of accessing the cookiestore directly?
            BasicCookieStore cookieStore = client.getCookieStore();
            List<Cookie> cookies = cookieStore.getCookies();
            Cookie[] cookieArray = cookies.toArray(new Cookie[cookies.size()]);
            try {
                cookieStore.clear();
                InputStream is = client.post(url, params);
                ret = AuthResponse.fromInputStream(is);
                if (ret.getJson().getData() != null) {
                    lastPassword = passwd;
                } else {
                    // an error occurred
                    cookieStore.addCookies(cookieArray);
                }
                is.close();
            } catch (Exception e) {
                // if failed, put the cookies back
                cookieStore.addCookies(cookieArray);
                throw new RedditEngineException(e);
            }
            return ret;
        }

        /**
         * Log out of reddit. Clears the cookie store
         */
        public void logout() {
            SimpleHttpClient client = SimpleHttpClient.getInstance();
            client.getCookieStore().clear();
        }

        /**
         * Get info about the currently authenticated user
         * 
         * @return {@link User}
         * @throws RedditEngineException
         */
        public User me() throws RedditEngineException {
            StringBuilder path = new StringBuilder();
            path.append(UrlUtils.REDDIT_SSL);
            path.append("/api/me.json");
            String url = path.toString();
            User response = new User();
            try {
                SimpleHttpClient client = SimpleHttpClient.getInstance();
                InputStream is = client.get(url, null);
                response = User.fromInputStream(is);
                is.close();
            } catch (Exception e) {
                RedditEngineException re = new RedditEngineException(e);
                throw re;
            }
            return response;
        }

        /**
         * Register a new user.
         * 
         * @param user         a valid, unused, username
         * @param passwd1      password for new user
         * @param passwd2      password for new user (again)
         * @param remember      specifies whether or not the session cookie returned should last beyond the current browser session 
         * @param email         (optional) the user's email address
         * @param captcha      the user's response to the CAPTCHA challenge
         * @param captchaIden   the identifier of the CAPTCHA challenge
         * @return {@link AuthResponse}
         * @throws RedditEngineException
         */
        public AuthResponse register(String user, String passwd1, String passwd2, boolean remember, String email,
                String captcha, String captcha_iden) throws RedditEngineException {
            StringBuilder path = new StringBuilder();
            path.append(UrlUtils.REDDIT_SSL);
            path.append("/api/register");
            String url = path.toString();

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("api_type", API_TYPE_JSON));
            params.add(new BasicNameValuePair("user", user));
            params.add(new BasicNameValuePair("passwd", passwd1));
            params.add(new BasicNameValuePair("passwd2", passwd2));
            if (captcha != null) {
                params.add(new BasicNameValuePair("captcha", captcha));
            }
            if (captcha_iden != null) {
                params.add(new BasicNameValuePair("iden", captcha_iden));
            }
            params.add(new BasicNameValuePair("rem", String.valueOf(remember)));
            if (email != null) {
                params.add(new BasicNameValuePair("email", email));
            }

            AuthResponse retval;
            try {
                SimpleHttpClient client = SimpleHttpClient.getInstance();
                InputStream is = client.post(url, params);
                retval = AuthResponse.fromInputStream(is);
                is.close();
            } catch (Exception e) {
                throw new RedditEngineException(e);
            }
            return retval;
        }

        /**
         * Update account email address and password.
         * newpass1 and newpass2 must be equal for a password change to succeed.
         * 
         * @param passwd   the current password   
         * @param email
         * @param newpass1   the new password
         * @param newpass2   the password again (for verification)
         * @param verify   boolean value
         * @return {@link JsonResponse}
         * @throws RedditEngineException 
         */
        public JsonResponse<?> updateUser(String passwd, String email, String newpass1, String newpass2, boolean verify)
                throws RedditEngineException {
            StringBuilder path = new StringBuilder();
            path.append(UrlUtils.REDDIT_SSL);
            path.append("/api/update");
            String url = path.toString();

            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("api_type", API_TYPE_JSON));
            if (passwd != null) {
                params.add(new BasicNameValuePair("curpass", passwd));
            }
            if (email != null) {
                params.add(new BasicNameValuePair("email", email));
            }
            if (newpass1 != null) {
                params.add(new BasicNameValuePair("newpass", newpass1));
            }
            if (newpass2 != null) {
                params.add(new BasicNameValuePair("verpass", newpass2));
            }
            params.add(new BasicNameValuePair("verify", String.valueOf(verify)));

            // response can be:
            // {"json": {"errors": [["WRONG_PASSWORD", "invalid password", "curpass"]]}}
            // {"json": {"errors": []}}
            JsonResponse<?> retval;
            try {
                SimpleHttpClient client = SimpleHttpClient.getInstance();
                InputStream is = client.post(url, params);
                retval = GsonTemplate.fromInputStream(is, JsonResponse.class);
                is.close();
            } catch (Exception e) {
                throw new RedditEngineException(e);
            }

            return retval;
        }

        private String lastPassword; // last known password the user has entered
    }