Skip to content

Commit

Permalink
Code refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Diaz committed Sep 29, 2016
1 parent 090e444 commit 14edc3f
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 87 deletions.
9 changes: 5 additions & 4 deletions app/src/main/java/com/icecream/snorlax/module/Snorlax.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.icecream.snorlax.module.feature.encounter.Encounter;
import com.icecream.snorlax.module.feature.mitm.Mitm;
import com.icecream.snorlax.module.feature.mock.Mock;
import com.icecream.snorlax.module.feature.rename.Rename;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.IXposedHookZygoteInit;
Expand All @@ -46,8 +47,8 @@ public class Snorlax implements IXposedHookLoadPackage, IXposedHookZygoteInit {
Capture mCapture;
@Inject
Encounter mEncounter;
//@Inject
//Ui mUi;
@Inject
Rename mRename;

private XSharedPreferences mXSharedPreferences;

Expand Down Expand Up @@ -76,13 +77,13 @@ private void handlePokemonGoLoadPackage(final ClassLoader classLoader) {
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
getComponent((Application) param.thisObject, classLoader, mXSharedPreferences).inject(Snorlax.this);

FeatureHelper.subscribe(mMitm, mMock, mCapture, mEncounter/*, mUi*/);
FeatureHelper.subscribe(mMitm, mMock, mCapture, mEncounter, mRename);
}
});
XposedHelpers.findAndHookMethod(Application.class, "onTerminate", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
FeatureHelper.unsubscribe(mMitm, mMock, mCapture, mEncounter/*, mUi*/);
FeatureHelper.unsubscribe(mMitm, mMock, mCapture, mEncounter, mRename);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2016. Pedro Diaz <igoticecream@gmail.com>
*
* 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
*
* 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.icecream.snorlax.module.feature.mitm;

import java.util.List;

import static POGOProtos.Networking.Envelopes.ResponseEnvelopeOuterClass.ResponseEnvelope;
import static POGOProtos.Networking.Requests.RequestOuterClass.Request;

@SuppressWarnings({"unused", "WeakerAccess", "FieldCanBeLocal"})
public interface MitmListener {

ResponseEnvelope onMitm(List<Request> requests, ResponseEnvelope envelope);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,44 @@
package com.icecream.snorlax.module.feature.mitm;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import android.util.LongSparseArray;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.icecream.snorlax.common.Strings;
import com.icecream.snorlax.module.util.Log;

import static POGOProtos.Data.PokemonDataOuterClass.PokemonData;
import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId;
import static POGOProtos.Inventory.InventoryDeltaOuterClass.InventoryDelta;
import static POGOProtos.Inventory.InventoryItemDataOuterClass.InventoryItemData;
import static POGOProtos.Inventory.InventoryItemOuterClass.InventoryItem;
import static POGOProtos.Networking.Envelopes.RequestEnvelopeOuterClass.RequestEnvelope;
import static POGOProtos.Networking.Envelopes.ResponseEnvelopeOuterClass.ResponseEnvelope;
import static POGOProtos.Networking.Requests.RequestOuterClass.Request;
import static POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType;
import static POGOProtos.Networking.Responses.GetInventoryResponseOuterClass.GetInventoryResponse;
import static android.R.attr.id;

@Singleton
final class MitmProvider {
@SuppressWarnings("unused")
public final class MitmProvider {

private final LongSparseArray<List<Request>> mRequests;
private final List<MitmListener> mListeners;

@Inject
MitmProvider(LongSparseArray<List<Request>> requests) {
mRequests = requests;
mListeners = new ArrayList<>();
}

public void addListenerResponse(MitmListener listener) {
if (listener != null) {
mListeners.add(listener);
}
}

public void removeListenerResponse(MitmListener listener) {
if (listener != null) {
mListeners.remove(listener);
}
}

ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk) {
Expand All @@ -65,7 +71,7 @@ ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk) {
RequestEnvelope envelope = RequestEnvelope.parseFrom(buffer);
MitmRelay.getInstance().call(envelope);

processOutBuffer(envelope);
setRequests(envelope);
}
}
catch (InvalidProtocolBufferException ignored) {
Expand All @@ -77,7 +83,7 @@ ByteBuffer processOutboundPackage(ByteBuffer roData, boolean connectionOk) {
return null;
}

private void processOutBuffer(RequestEnvelope envelope) {
private void setRequests(RequestEnvelope envelope) {
mRequests.put(
envelope.getRequestId(),
envelope.getRequestsList()
Expand All @@ -98,10 +104,15 @@ ByteBuffer processInboundPackage(ByteBuffer roData, boolean connectionOk) {
ResponseEnvelope envelope = ResponseEnvelope.parseFrom(buffer);
MitmRelay.getInstance().call(envelope);

ByteBuffer processed = processInBuffer(envelope);

if (processed != null) {
return processed;
final List<Request> requests = getRequests(envelope);
if (requests != null && mListeners.size() > 0) {
for (MitmListener listener : mListeners) {
ResponseEnvelope temp = listener.onMitm(requests, envelope);
if (temp != null) {
envelope = temp;
}
}
return ByteBuffer.wrap(envelope.toByteArray());
}
}
}
Expand All @@ -114,72 +125,10 @@ ByteBuffer processInboundPackage(ByteBuffer roData, boolean connectionOk) {
return null;
}

private ByteBuffer processInBuffer(ResponseEnvelope envelope) throws InvalidProtocolBufferException {
List<Request> requests = mRequests.get(envelope.getRequestId());

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

boolean isDone = false;
for (int i = 0; i < requests.size(); i++) {
if (requests.get(i).getRequestType() == RequestType.GET_INVENTORY) {
ByteString processed = processInventoryResponse(GetInventoryResponse.parseFrom(envelope.getReturns(i)));

if (processed != null) {
ResponseEnvelope.Builder builder = envelope.toBuilder();
builder.setReturns(i, processed);
envelope = builder.build();
isDone = true;
}
}
}
private List<Request> getRequests(ResponseEnvelope envelope) {
final long id = envelope.getRequestId();
List<Request> requests = mRequests.get(id);
mRequests.remove(id);

if (!isDone) {
return null;
}

return ByteBuffer.wrap(envelope.toByteArray());
}

private ByteString processInventoryResponse(GetInventoryResponse response) {
if (!response.getSuccess() || !response.hasInventoryDelta()) {
return null;
}

boolean isDone = false;
GetInventoryResponse.Builder inventory = response.toBuilder();
InventoryDelta.Builder inventoryDelta = inventory.getInventoryDelta().toBuilder();
for (int i = 0; i < inventoryDelta.getInventoryItemsCount(); i++) {
InventoryItem.Builder inventoryItem = inventoryDelta.getInventoryItems(i).toBuilder();
InventoryItemData.Builder itemData = inventoryItem.getInventoryItemData().toBuilder();

if (itemData.getPokemonData().getPokemonId() != PokemonId.MISSINGNO) {
PokemonData.Builder Pokemon = itemData.getPokemonData().toBuilder();
String nickname = Pokemon.getNickname();

if (Strings.isEmpty(nickname)) {
Pokemon.setNickname(
String.format(
"%s/%s/%s",
String.valueOf(Pokemon.getIndividualAttack()),
String.valueOf(Pokemon.getIndividualDefense()),
String.valueOf(Pokemon.getIndividualStamina())
)
);
itemData.setPokemonData(Pokemon);
inventoryItem.setInventoryItemData(itemData);
inventoryDelta.setInventoryItems(i, inventoryItem);
inventory.setInventoryDelta(inventoryDelta);
isDone = true;
}
}
}
if (isDone) {
return inventory.build().toByteString();
}

return null;
return requests;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (c) 2016. Pedro Diaz <igoticecream@gmail.com>
*
* 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
*
* 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.icecream.snorlax.module.feature.rename;

import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.icecream.snorlax.common.Strings;
import com.icecream.snorlax.module.feature.Feature;
import com.icecream.snorlax.module.feature.mitm.MitmListener;
import com.icecream.snorlax.module.feature.mitm.MitmProvider;

import static POGOProtos.Data.PokemonDataOuterClass.PokemonData;
import static POGOProtos.Enums.PokemonIdOuterClass.PokemonId;
import static POGOProtos.Inventory.InventoryDeltaOuterClass.InventoryDelta;
import static POGOProtos.Inventory.InventoryItemDataOuterClass.InventoryItemData;
import static POGOProtos.Inventory.InventoryItemOuterClass.InventoryItem;
import static POGOProtos.Networking.Envelopes.ResponseEnvelopeOuterClass.ResponseEnvelope;
import static POGOProtos.Networking.Requests.RequestOuterClass.Request;
import static POGOProtos.Networking.Requests.RequestTypeOuterClass.RequestType;
import static POGOProtos.Networking.Responses.GetInventoryResponseOuterClass.GetInventoryResponse;

@Singleton
public final class Rename implements Feature, MitmListener {

private final MitmProvider mMitmProvider;

@Inject
Rename(MitmProvider mitmProvider) {
mMitmProvider = mitmProvider;
}

@Override
public void subscribe() {
unsubscribe();
mMitmProvider.addListenerResponse(this);
}

@Override
public void unsubscribe() {
mMitmProvider.removeListenerResponse(this);
}

@Override
public ResponseEnvelope onMitm(List<Request> requests, ResponseEnvelope envelope) {
for (int i = 0; i < requests.size(); i++) {
if (requests.get(i).getRequestType() == RequestType.GET_INVENTORY) {
try {
ByteString processed = processInventory(GetInventoryResponse.parseFrom(envelope.getReturns(i)));

if (processed != null) {
envelope = envelope.toBuilder().setReturns(i, processed).build();
}
}
catch (InvalidProtocolBufferException ignored) {
}
}
}
return envelope;
}

private ByteString processInventory(GetInventoryResponse response) {
if (!response.getSuccess() || !response.hasInventoryDelta()) {
return null;
}

GetInventoryResponse.Builder inventory = response.toBuilder();
InventoryDelta.Builder delta = inventory.getInventoryDelta().toBuilder();

for (int i = 0; i < delta.getInventoryItemsCount(); i++) {

InventoryItem.Builder item = delta.getInventoryItems(i).toBuilder();
InventoryItemData.Builder data = item.getInventoryItemData().toBuilder();

if (data.getPokemonData().getPokemonId() != PokemonId.MISSINGNO) {
PokemonData.Builder pokemon = data.getPokemonData().toBuilder();

if (Strings.isEmpty(pokemon.getNickname())) {
pokemon.setNickname(String.format(
"+ %s/%s/%s",
String.valueOf(pokemon.getIndividualAttack()),
String.valueOf(pokemon.getIndividualDefense()),
String.valueOf(pokemon.getIndividualStamina())
));
}
data.setPokemonData(pokemon);
}

item.setInventoryItemData(data);
delta.setInventoryItems(i, item);
}
return inventory.setInventoryDelta(delta).build().toByteString();
}
}

0 comments on commit 14edc3f

Please sign in to comment.