вторник, 27 августа 2013 г.

Android: проблема с доступом к сети в разных версиях API

Решение:

if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }

Данный кусок кода ставим в onCreate.
И не забываем про <uses-permission android:name="android.permission.INTERNET" /> в манифесте.

вторник, 23 июля 2013 г.

Подводные камни в Java

Иногда бывает засада в простых вещах, но которые сложно отловить и отдебажить.
Например, byte:

Java byte     -128..127       8 bits
C#   byte     0..255             8 bits

Это надо учитывать при битовых операциях и при работе с шестнадцатеричными числами.
Скажем, 0xd3 в C# - это 211, а в Java -83

Ещё одна вещь, которая может содержать потенциальную ошибку заключается в том, что если в Java-коде у вас число начинается с 0, то оно преобразуется в восьмеричное число (кто придумал этот бред?). Поэтому, если вы напишете 0123, (предполагая, что это будет десятичное 123), то будьте уверены, что это это будет восьмеричное 123, которое в десятичном виде является числом 173.

понедельник, 6 мая 2013 г.

Правильно читаем кириллицу в UTF-8 из JSON-ответа. Десериализация JSON

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Xml;

....

[DataContract]
        public class iiiText
        {
            [DataMember]
            public String value;
            [DataMember]
            public String delay;
            [DataMember]
            public String status;
            [DataMember]
            public String showRate;
        }

        [DataContract]
        public class iiiAnimation
        {
            [DataMember]
            public String type;
            [DataMember]
            public String duration;
            [DataMember]
            public String isFaded;
        }

        [DataContract]
        public class iiiResult
        {
            [DataMember]
            public iiiText text;
            [DataMember]
            public iiiAnimation animation;
            [DataMember]
            public String navigation;
            [DataMember]
            public String token;
            [DataMember]
            public String showExpSys;
            [DataMember]
            public String rubric;
        }

        [DataContract]
        public class iiiClass
        {
            [DataMember]
            public iiiResult result;
            [DataMember]
            public String id;
        }

        public class JSONHelper
        {
            public static T Deserialise(string json)
            {
                using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
                {
                    var serialiser = new DataContractJsonSerializer(typeof(T));
                    return (T)serialiser.ReadObject(ms);
                }
            }

        }


static void Main(string[] args)
        {
            String ChatBotId = "xxxxxx-xxxx-xxx-xxx";

            while (true)
            {
                String message = Console.ReadLine();
                String url =
                    String.Format(
                        "https://...{0}...{1}..."
                        , ChatBotId
                        , HttpUtility.UrlEncode(message));
                HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(url);
                HttpWebResponse response = (HttpWebResponse) request.GetResponse();
                StreamReader responseReader = new StreamReader(response.GetResponseStream(),
                                                               Encoding.GetEncoding("windows-1251"));
                string html = responseReader.ReadToEnd();

                Regex r = new Regex(@".+?\((.+?)\)$");
                Match m = r.Match(html);
                if (m.Success)
                    html = m.Groups[1].Value;

                var answerData = JSONHelper.Deserialise(html);
                Console.WriteLine("{0}", answerData.result.text.value);
            }
        }

вторник, 2 апреля 2013 г.

Переводим PHP-сайт сайт на ASP.NET MVC без изменения вида ссылок

Предположим, что у нас есть PHP-сайт со страницей http://site.com/res.php?anyparameters и мы хотим настроить маршрутизацию в ASP.NET MVC4 так, чтобы эта php-ссылка осталась без изменений (у клиентов уже есть софт, настроенный на работу с этим урлом). При этом в GET-запросе может быть параметр с именем "action" ("action=addfunds", "action=logout",...)
Тогда делаем следующее

1. В методе RegisterRoutes класса RouteConfig прописываем следующие URL-паттерны:

routes.MapRoute(
                name: "ApiDocs",
                url: "api",
                defaults: new { controller = "Page", action = "Api" }
            );

 routes.MapRoute(
                name: "pull_php",
                url: "pull.php",
                defaults: new { controller = "Method", action = "Pull", key = UrlParameter.Optional }
            );

routes.MapRoute(
                name: "pull",
                url: "pull",
                defaults: new { controller = "Method", action = "Pull", key = UrlParameter.Optional }
            );

routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}",
                defaults: new {controller = "Page", action = "Main"});

2. В контроллере Method пишем
[HttpGet]
        public ActionResult Pull(String key, String id)
        {
            var apiAction = Request["action"];
            ...
            return View(result);
        }

Вот и всё.

вторник, 26 февраля 2013 г.

RSA-шифрование в Android (Java)

В одном своём проекте я решил реализовать безопасную переписку между двумя пользователями используя мобильное приложение на Android.
Задача сводилась к тому, чтобы пользователь мог создать себе пару ключей (публичный/приватный), иметь возможность сохранить их в виде Base64-строки (для передачи по http и простого хранения в виде текстовой строки), а также чтобы можно было восстановить эти ключи, сохранённые в Base64 и использовать их для шифрования.


Пример использования класса Crypto (Я-Alex, у меня есть пара ключей public/private; Ustas-мой собеседник, передающий сообщение мне)

Юстас - Алексу
--------------
на стороне Юстаса (необходимо предварительно получить открытый(публичный) ключ Алекса):
Crypto Ustas = new Crypto();
Ustas.GenerateKeys();
String toAlex = Ustas.RSAEncrypt("Привет!", Alex.publicBase64);

на стороне Алекса:
Crypto Alex = new Crypto();
Alex.GenerateKeys();
String fromUstas = Alex.RSADecrypt(toAlex, Alex.privateBase64);


класс Crypto.java:
------------------
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import android.util.Base64;
import android.util.Log;

public class Crypto
{
    KeyPairGenerator kpg;
    KeyPair kp ;
    int keySize = 1024;
    RSAPublicKey key;

    public String publicBase64;
    public String privateBase64;
   
    public void GenerateKeys() throws NoSuchAlgorithmException
    {
        kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        kp = kpg.genKeyPair();
        PublicKey publicKey = kp.getPublic();
        PrivateKey privateKey = kp.getPrivate();

        byte[] publicBytes = publicKey.getEncoded();
        publicBase64 = Base64.encodeToString(publicBytes, Base64.DEFAULT);

        byte[] privateBytes = privateKey.getEncoded();
        privateBase64 = Base64.encodeToString(privateBytes, Base64.DEFAULT);
    }
   
    public String RSAEncrypt(final String plain, String publicKeyBase64) throws NoSuchAlgorithmException, NoSuchPaddingException,
        InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
       
        PublicKey publicKey;
        byte[] publicBytes = Base64.decode(publicKeyBase64, Base64.DEFAULT);
        publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicBytes));

        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(plain.getBytes());

        String encrypted = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
        return encrypted;
    }

    public String RSADecrypt(final String encrypted, String privateKeyBase64) throws NoSuchAlgorithmException, NoSuchPaddingException,
        InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidKeySpecException {
   
        byte[] privateBytes = Base64.decode(privateKeyBase64, Base64.DEFAULT);
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateBytes));
       
        byte[] encryptedBytes = Base64.decode(encrypted, Base64.DEFAULT);
        Cipher cipher1 = Cipher.getInstance("RSA");
        cipher1.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher1.doFinal(encryptedBytes);
        String decrypted = new String(decryptedBytes);
        return decrypted;
    }
   
}

Как выложить свой проект на github

I. Подготовка
    1. Зарегистрироваться на github
    2. Создать проект
    3. Установить git

II.
1.
github: new repository
git config --global user.name "my_username"
git config --global user.email "my@email.com"
git config --global core.autocrlf true
git config --global core.safecrlf true

2. Устанавливаем TortoiseGit
3. На папке проекта ПКМ - Add... и добавляем все файлы проекта в репозиторий.
4. Выполняем команды (ПКМ на папке проекта - Git Bash Here):

$ git remote add origin https://github.com/my_username/my_project.git
$ git push -u origin master