晚来天欲雪,能饮一杯无

个人记录


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索

valatile关键字

发表于 2020-02-12

起两个作用

  1. 内存的可见性
    在程序工作的过程中,会存在工作内存(比如多线程工作时的变量内存)和主内存,在修改完这个线程对象的一瞬间,该线程的工作内存已经改变,主内存还没有改变,其他线程可能存在数据不一致的问题
    使用valatile修饰后,该对象会立刻刷新到主内存和其他工内存。
  2. 顺序性,
    防止指令重排序。java在重新编译后,为了优化,字节码的顺序可能和我们所定义的顺序不一致,加上valatile,可以避免这种情况。

装饰模式vs继承

发表于 2020-02-12

介绍

装饰模式又名包装(Wrapper)模式

  1. 装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案
  2. 装饰模式以对客户透明的方式动态的给一个对象附加更多的责任。换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。
  3. 装饰模式可以在不创造更多子类的情况下。将对象的功能甲乙扩展。
  4. 装饰模式吧客户端的调用委派到被装饰类。装饰模式的关键在于这种扩展完全是透明的
  5. 装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。他是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰模式的角色:

  1. 抽象构建角色(component):给出一个抽象接口,以规范准备接受附加责任的对象。
  2. 具体构建角色(concrete Component):定义一个将要接受附加责任的类。
  3. 装饰角色(Devorator):持有一个构建对象的引用,并定义一个与抽象构建接口一致的接口。
  4. 具体装饰角色(Concrete Decorator):负责给构建对象“贴上”附加的责任。

装饰模式的特点:

  1. 装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。
  2. 装饰对象包含一个真实对象的引用。
  3. 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  4. 装饰对象可以在转发这些请求以前或者以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来是想对给定类的功能扩展。

核心代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Component{
void doSomething();
}

public class Decoraror implements Component{

private Component component;

public Decorator(Component component){
this.component = component;
}

public void doSomething(){
component.doSomething();
}
}

开发经验总结

发表于 2020-02-10
  1. 接口返回的数据在数据库对应字符串,最好不好返回boolean类型,返回int或者string,考虑到安全的话,不要讲数据库代表的数字含义直接返回,
    如: 数据库是 1:成功;0:失败,返回时可以返回”success”:成功 ; “failure”:失败,返回时可以返回
  2. 对于数据库内容一定要有追溯性,不能为了业务方便,直接按照业务执行。 如查询记录一些日志,与其他冲突时,先删除以前全部的相关日志,再新增。(属于设计问题)
  3. 魔鬼数字,不要写成 STRING_1=”1” ,这种写法还是属于魔鬼数字,STRING_1代表什么含义还是不知道,不能偷懒。
  4. 对于if条件,如果是两种情况,且确认值的情况下,需要全部判断(特别复杂的除外,如多个条件同时判断,多个条件结果重复)。
    如: 字符串str可能是1或者2,请写成if(str == ‘1’){}else if(str ==’2’ ){}else{}不要写成 if(str ==’1’ ){}else{}
  5. 命名最好不要简写,最终目标是,看见变量名就能知道这个变量是做什么用的,不要让别人猜,产生歧义。
  6. 遇见代码格式变化较大或者较多时,将原版代码格式化提交后,再讲自己代码提交,这样方便对比追溯。
  7. 不要使用反歧义的boolean。
    如: 用true表示未完成,false表示完成。
  8. 对于稍长的字符串,使用时如果不是自动生成,请复制后使用,不建议手打,容易出错。
    如: mabatis中mapper.xml和mapper.java对应的表名,空间名。

PreparedStatement

发表于 2019-12-28

PreparedStatement 是一个特殊的Statement对象,如果我们只是来查询或者更新数据的话,最好用PreparedStatement代替Statement,因为它有以下有点:

  • 简化Statement中的操作
  • 提高执行语句的性能
  • 可读性和可维护性更好
  • 安全性更好。
  • 使用PreparedStatement能够预防SQL注入攻击,所谓SQL注入,指的是通过把SQL命令插入到Web表单提交或者输入域名或者页面请求的查询字符串,最终达到欺骗服务器,达到执行恶意SQL命令的目的。注入只对SQL语句的编译过程有破坏作用,而执行阶段只是把输入串作为数据处理,不再需要对SQL语句进行解析,因此也就避免了类似select * from user where name=’aa’ and password=’bb’ or 1=1的sql注入问题的发生。
Statement 和 PreparedStatement之间的关系和区别.
  • 关系:PreparedStatement继承自Statement,都是接口
  • 区别:PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高

隐藏(hide)和重写(override)和遮掩(obscure)遮蔽(shadow)和重载(overload)

发表于 2019-11-28

重写(override)

一个实例方法可以overide在其超类中可以访问到的具有相同签名的所有方法,从而可以动态分派(dynamic dispatch),VM基于运行时类型来选择要调用的覆写方法。

1
2
3
4
5
6
7
8
class Base {
public void f() {
}
}
class Derived extends Base {
public void f() {
} // overrides Base.f()
}

隐藏 hide

一个域,静态方法,或成员类型可以分别被隐藏(hide)在其超类可以访问到的具有相同名字的所有域、静态方法或成员类型。hide几个成员将阻止其被继承。
// 错误样例

1
2
3
4
5
6
7
8
class Base {
public static void f() {
}
}
class Derived extends Base {
private static void f() {
} // hides Base.f()
}

// 正确样例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Base {
static int a = 1;
int b = 3;
public static void f() {
System.out.println("Base");
}
}
class Derived extends Base {
static int a = 2;
int b = 4;
public static void f() {
System.out.println("Derived");
} // hides Base.f()
}
public class Hide {
public static void main(String[] args) {
Base.f();
Derived.f();
System.out.println(Base.a);
System.out.println(Derived.a);
System.out.println((new Base()).b);
System.out.println((new Derived()).b);
System.out.println(((Base) (new Derived())).b);
}
}

重载(overload)

在某个类中的方法可以重载(overload)另一个方法,只要它们具有相同的名字和不同的签名。由调用所指定的重载方法是在编译期选定的。

遮蔽(shadow)

一个变量、方法或类型可以分别遮蔽(shadow)在一个闭合的文本范围内的具有相同名字的所有变量、方法或类型。如果一个实体被遮蔽了,那么你用它的简单名是无法引用到它的;根据实体的不同,有时你根本就无法引用到它。

1
2
3
4
5
6
7
class WhoKnows {
static String sentence = "I don't know.";
public static void main(String[] args) {
String sentence = "I know!"; // shadows static field
System.out.println(sentence); // prints local variable
}
}

  1. 编译器在选择在运行期被调用的方法时,所做的第一件事就是在肯定能找到该方法的范围内挑选。编译器将在包含具有恰当名字的方法的最小闭合范围内挑选,下例中就是ImportDuty类,它包含了从Object继承的方法toString。
  2. 导入的toString方法被继承的toString方法所遮蔽(shadow)
  3. 本身就属于某个范围的成员在该范围内与静态导入相比具有优先权。
    以下代码无法被编译通过
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import static java.util.Arrays.toString;
    class ImportDuty {
    public static void main(String[] args) {
    printArgs(1, 2, 3, 4, 5);
    }
    static void printArgs(Object... args) {
    System.out.println(toString(args));
    }
    }

遮掩(obscure)

一个变量可以遮掩具有相同名字的一个类型,只要它们都在同一个范围内:如果这个名字被用于变量与类型都被许可的范围,那么它将引用到变量上。相似地,一个变量或一个类型可以遮掩一个包。遮掩是唯一一种两个名字位于不同的名字空间的名字重用形式,这些名字空间包括:变量、包、方法或类型。

1
2
3
4
5
6
7
8
// 变量遮掩了类型
public class Obscure {
static String System; // Obscures type java.lang.System
public static void main(String[ ] args) {
// Next line won't compile: System refers to static field
System.out.println(”hello, obscure world!“);
}
}

当一个变量和一个类型具有相同的名字,并且他们位于相同的作用域时,变量名具有优先权 JLS 6.5.2,变量将遮掩(obscure)类型名。相似地,变量名和类型名可以遮掩包名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ShadowOfGray {
public static void main(String[] args) {
System.out.println(X.Y.Z); // 输出结果White
}
}
class X {
static class Y {
static String Z = "Black";
}
static C Y = new C();
}
class C {
String Z = "White";
}

iterator和iterable

发表于 2019-10-28

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
Iterator是java.util包下的接口:

1
2
3
4
5
6
package java.util;
public interface Iterator{
boolean hasNext();
Object next();
void remove();
}

Iterable是java.lang下的接口:

1
2
3
4
5
package java.lang;
import java.util.Iterator;
public interface Iterable{
Iterator iterator();
}

  1. 在jdk 1.5以后,引入了Iterable,使用foreach语句(增强型for循环)必须使用Iterable类。
  2. Collection继承于Iterable而不是Iterator接口。
    Iterable的子类是Collection,Collection的子类是List,Set,这些是数据结构的类,用于存放数据。
    Iterator是定义迭代逻辑的类,让迭代逻辑和数据结构分离开来,这样的好处是可以在一种数据结构上实现多种迭代逻辑
  3. 每一次调用Iterable的Iterator()方法,都会返回一个从头开始的Iterator对象,各个Iterator对象之间不会相互干扰,保证了(多线程)可以同时对一个数据结构进行多个遍历。

解析藏宝阁密文

发表于 2019-10-27

以下内容仅作为技术讨论使用,务商业使用。

在查看梦幻藏宝阁的时,像了解下对于数据的展示,这种平台是如何操作,于是对网页数据进行了分析,以下是分析出数据的方法。

对于一些敏感数据,网站就需要对其进行混淆,增加爬虫的成本。

例如网页https://xyq.cbg.163.com/equip?s=212&eid=201908132100113-212-AQYRMWM0DU8U&o&equip_refer=58

分析其返回的response,发现返回值并没有直接赋值上去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<tr>
<th>气血:</th>
<td><%= pet.blood %>/<%= pet.max_blood %></td>
<th>体质:</th>
<td><%= pet.soma %></td>
</tr>
<tr>
<th>魔法:</th>
<td><%= pet.magic %>/<%= pet.max_magic %></td>
<th>法力:</th>
<td><%= pet.magic_powner %></td>
</tr>
<tr>
<th>攻击:</th>
<td><%= pet.attack %></td>
<th>力量:</th>
<td><%= pet.strength %></td>
</tr>

由pet对象来获取,则在网页中查找这个对象

1
2
3
4
<%
var pet = this.pet_attrs;
var enhance_info = this.enhance_info || {};
%>

继续查找pet_attrs

1
2
var pet_desc = parse_desc_info($("equip_desc_" + el.getAttribute("data_equipid")).value);
var pet_attrs = get_pet_attrs_info(pet_desc, true);

这串代码中,根据equip_desc_查到到了这个网页的主要信息内容。

1
2
3
<textarea id="equip_desc_value" style="display:none">
超级神兔;102273;169;3269;1920;2425;964;280;100;300;189;1092;189;189;0;956;3269;1920;65432;1;1600;1600;5500;3500;1400;1400;1300;425|404|416|405|422;0;1;0;2;0;0;(["tmp_lingxing":0,"core_close":0,"lastchecksubzz":0,"summon_core":([901:({5,0,([]),}),924:({5,0,([]),}),932:({5,0,([]),}),]),"left_qlxl":7,"weaken":0,"growthMax":1236,"iJjFeedCd":0,"summon_equip4_type":0,"carrygradezz":0,"MP_MAX":3050,"sjg":0,"summon_color":0,"csavezz":"1600|1600|1400|1400|5500|3500","MS_MAX":1800,"jj_extra_add":0,"iRealColor":0,"SPD_MAX":1550,"DEF_MAX":1550,"summon_equip4_desc":"","HP_MAX":5500,"jinjie":(["core":([]),"cnt":0,"lx":0,]),"ATK_MAX":1550,"strengthen":0,])
</textarea>

过程有些顺利

接下来在解析角色时,发现equip_desc_value的value值并没有直接体现出来。
如:https://xyq.cbg.163.com/equip?s=579&eid=201907212200113-579-5ZF1WK0H3GFP&equip_refer=26&view_loc=reco_left

1
<textarea id="equip_desc_value" style="display:none"><textarea id="equip_desc_value" style="display:none">@VB38(因内容太多,此处省略)DAxOSJ9@</textarea>

继续追本溯源查找equip_desc_value,查找到以下代码

1
var role_info = js_eval(lpc_2_js(get_equip_desc('equip_desc_value')));

通过打断点的方式发现get_equip_desc方法为解析加密的内容的核心方法。(lpc_2_js是将字符串转为对象字符串的方法,并不是核心方法)
继续往下查找get_equip_desc方法

1
2
3
function get_equip_desc(elemId) {
return decode_desc($(elemId).value);
}

好吧,继续查看decode_desc方法,看到这种代码,终于进入主题了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
!function(_0xcbc80b) {
_0xcbc80b['\x64\x65\x63\x6f\x64\x65\x5f\x64\x65\x73\x63'] = function g(_0x1c0cdf) {
if (_0x1c0cdf = _0x1c0cdf['\x72\x65\x70\x6c\x61\x63\x65'](/^\s+|\s+$/g, ''),
!/^@[\s\S]*@$/[_0x3a8e('0x0')](_0x1c0cdf))
return _0x1c0cdf;
var _0x36ab38 = (/\b_k=([^;]*)/['\x65\x78\x65\x63'](document['\x63\x6f\x6f\x6b\x69\x65']) || [])[0x1] || '';
if (_0x1c0cdf = _0x1c0cdf['\x72\x65\x70\x6c\x61\x63\x65'](/^@|@$/g, ''),
/^[^@]+@[\s\S]+/['\x74\x65\x73\x74'](_0x1c0cdf)) {
var _0x33c80e = _0x1c0cdf['\x69\x6e\x64\x65\x78\x4f\x66']('\x40');
_0x36ab38 = _0x1c0cdf[_0x3a8e('0x1')](0x0, _0x33c80e),
_0x1c0cdf = _0x1c0cdf['\x73\x75\x62\x73\x74\x72\x69\x6e\x67'](_0x33c80e + 0x1);
}
var _0x1b3f48 = function s(_0x1c0cdf) {
try {
return _0xcbc80b['\x65\x76\x61\x6c']('\x28' + _0x1c0cdf + '\x29');
} catch (_0x40b9c3) {
return null;
}
}(_0x1c0cdf = _0xcbc80b[_0x3a8e('0x2')](_0x1c0cdf));
_0x1b3f48 && '\x6f\x62\x6a\x65\x63\x74' == typeof _0x1b3f48 && _0x1b3f48['\x64'] && (_0x1b3f48 = _0x1b3f48['\x64']);
for (var _0x20b9fa = [], _0x10503c = 0x0, _0x1a524d = 0x0; _0x1a524d < _0x1b3f48['\x6c\x65\x6e\x67\x74\x68']; _0x1a524d++) {
var _0x3641ed = _0x1b3f48['\x63\x68\x61\x72\x43\x6f\x64\x65\x41\x74'](_0x1a524d)
, _0x341952 = _0x36ab38[_0x3a8e('0x3')](_0x10503c % _0x36ab38['\x6c\x65\x6e\x67\x74\x68']);
_0x10503c += 0x1,
_0x3641ed = 0x1 * _0x3641ed ^ _0x341952,
_0x20b9fa[_0x3a8e('0x4')](_0x3641ed['\x74\x6f\x53\x74\x72\x69\x6e\x67'](0x2));
}
return function d(_0x1c0cdf) {
for (var _0x36ab38 = [], _0x33c80e = 0x0; _0x33c80e < _0x1c0cdf['\x6c\x65\x6e\x67\x74\x68']; _0x33c80e++)
_0x36ab38['\x70\x75\x73\x68'](_0xcbc80b['\x53\x74\x72\x69\x6e\x67']['\x66\x72\x6f\x6d\x43\x68\x61\x72\x43\x6f\x64\x65'](_0xcbc80b['\x70\x61\x72\x73\x65\x49\x6e\x74'](_0x1c0cdf[_0x33c80e], 0x2)));
return _0x36ab38['\x6a\x6f\x69\x6e']('');
}(_0x20b9fa);
}
;
}(window);

对此先将方法去混淆.刚开始看到 _0x1c0cdf[_0x3a8e(‘0x1’)](0x0, _0x33c80e) 这种写法我还懵圈了老半天,这是种什么写法。后来在去混淆的过程中发现 _0x3a8e(‘0x1’) 的值是substring,这不就是方法名吗,然后意识到,这不就是js调用方法的另一种写法吗 ,只是很久不用这种写法第一眼没有认出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
function decode_desc(ciphertext) {
if (ciphertext = ciphertext.replace(/^\s+|\s+$/g, ''),
!/^@[\s\S]*@$/.test(ciphertext))
return ciphertext;
var _0x36ab38 = "";//(/\b_k=([^;]*)/.exec(document.cookie) || [])[0x1] || '';
if (ciphertext = ciphertext.replace(/^@|@$/g, ''),
/^[^@]+@[\s\S]+/.test(ciphertext)) {
var num = ciphertext.indexOf('@');
_0x36ab38 = ciphertext.substring(0, num),
ciphertext = ciphertext.substring(num + 0x1);
}
debugger;
var _0x1b3f48 = function s(ciphertext) {
try {
return window.eval('(' + ciphertext + ')');//
} catch (_0x40b9c3) {
return null;
}
}(ciphertext = window.atob(ciphertext));//解码
_0x1b3f48 && 'object' == typeof _0x1b3f48 && _0x1b3f48['d'] && (_0x1b3f48 = _0x1b3f48['d']);//从对象{'d':'xxx'} 取到xxx
var str=_0x1b3f48;
//numList 是二进制数字的集合
for (var numList = [], j = 0, i =0; i < str.length; i++) {
var charCode = str.charCodeAt(i)
, _0x341952 = _0x36ab38.charCodeAt(j % _0x36ab38.length);//_0x36ab38 是一个短的字符串 如 QOGBzhZ8hvVKgka8
j ++,
charCode = 0x1 * charCode ^ _0x341952,
numList.push(charCode.toString(2));
}
return function d(ciphertext) {
for (var arr = [], i = 0; i < ciphertext.length; i++)
arr.push(window.String.fromCharCode(window.parseInt(ciphertext[i], 2)));
return arr.join('');
}(numList);
}

至此提供一个完整版js解密代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
function decodeObject(){
var role_info = js_eval(lpc_2_js(decode_desc( "@QOGBzhZ8hvVKgka8@eyJkIjogInlcdTAwMTRlMVx1MDAxMlxyNElcdTAwMDFUbGM8NkhcdTAwMTRzJlx1MDAwNSdcdTAwMWJcdTAwMWIua1x1MDAwM1x1MDAxZmdpXVtNXHUwMDFhOFxmJjFcdTAwMTJKYFxmXkZufF9HQ1FcdTAwMTk/XHUwMDE4XHUwMDBmXHUwMDFiXHUwMDEweFx1MDAwMllAbnJLSTV5XHUwMDBlJlx1MDAwNi5cdTAwMTYmP084XHUwMDE5PyVcdTAwMTNJW1x0fW1cdTAwMDYhXHUwMDEyODVRXHUwMDA2XHUwMDAyXHUwMDAyJFx1MDAxM1xuXHJcdTAwMWFreHZ3Vkozdlx1MDAxZFx1MDAwMiVcdTAwMDVcdTAwMTJcdTAwMDZDXHUwMDAyYWNlK1x1MDAxZFx1MDAwNzVcXFx1MDAwNlx1MDAxMyU4OFx1MDAxOFx1MDAwME5zdXV2TFxcdlx1MDAxYVx1MDAwMTs3LDgqXHJUc3V2dEpEeEpcclx1MDAxOFwiXHUwMDE0XHUwMDBiXHUwMDBlXHUwMDE3XT1tfXJWSjNsXHUwMDA3XHUwMDAyNycqXG5cdTAwMDZ8NClcdTAwMTgjXHUwMDE2XHUwMDA0eFx1MDAwMlxcRGJnRVxiL1k8KmV4WFx1NWE1OVx1NGUwYVxmXFxCdGdFXHUwMDAyMls5ICguWFJrXHJEVD9cdTAwMDZcdTAwMTdJW1x1MDAwZmV9a2AuKVx1MDAwNVEpXHUwMDFhOlx1MDAxYlxiXHUwMDAyXHUwMDBmTHN1d25YXHUwMDAxXHRTXHUwMDAxJjlcIlx0XHUwMDFmQ1x1MDAwMmJcdTAwN2ZrYFx1MDAxMyE5V1x1MDAwNlRsel5HQ30pP1xyNVhSalx1MDAxNEpcdTAwMWZcdTAwMTMzXHUwMDE3XHUwMDFmMlM4e2V4SkR4UTpcdTAwMTMlXHUwMDE0Jlx1MDAwN1xyXHUwMDFha35ydlZKPFlcdTAwMWFcdTAwMWJcdCdcdTAwMDJcdTAwMWRcdTAwMDRUc3V3blhcdTAwMDFcYllcdTAwMGJcdTAwMTN0cVVHQ1FcdTAwMTJcYlx1MDAxMy1cdTAwMGVcdDZ5XHUwMDA1XHUwMDE5IyVcdTAwMTNJW1xifW0uXHUwMDA3XHUwMDAyXHUwMDE4LmtcdTAwMDNcdTAwMWZjaV1bTVx1MDAxYThcdTAwMWNcIjVcdFx1MDAwMzNcdTAwMWFSRnppXHUwMDBlL1x1MDAwNF5cdTAwMGVcdTAwMGUrLlhSb1xiWVp0OVx1MDAwMlx1MDAwNVx1MDAxNVx1MDAxYWtcdTAwN2ZrYFx1MDAxOVx1MDAwNzdVXHUwMDFkKTFcIlx1MDAwM0lbXGJ9bVwiLFx1MDAxZlx1MDAxYT1BSkxie0tJXGJ9Iz0mLFx1MDAwZVx1MDAxYSNcdTAwMWFSRnppXHUwMDBlL1x1MDAwNEBcdTAwMGVcdTAwMGUrLlhSb1x1MDAwZVFadFwiJVx1MDAwZVx1MDAwMEslXHUwMDFjLCtJSmBcYkRUP1x1MDAwZVx1MDAxZlx1MDAxYlx1MDAxNWs6JnZgQFh2XHUwMDFhXHRcdTAwMTIyXHUwMDFiXGJcdTAwMDJcdTAwMGZMc3V3blhcbjNcXEpMZmdFXHUwMDAyLko2XHUwMDAwISRcdTAwMWZcdTAwMWF4XHUwMDAyWFp0M1x1MDAwZVxuXHUwMDBmQSRtfXJWSjRXXHUwMDFhXHUwMDFiNyc4XHUwMDAzXHUwMDBlSlwiKmV4SkR4WydcdTAwMDQxaV1JXHU3MDJkXHU3YmQ2XHU5YTg5XHU2MjA0ZW5YXHUwMDE4P0xKTH4wXHUwMDFhQk1cdTAwMWE+PS5cdTAwMWRcYlx0OV1KTGRnRVx1MDAwMiVdXCIsZXhKRHhwXHUwMDFkXHUwMDExM1x1MDAwM1xiXHUwMDE5XHUwMDEyXXN1b1x1MDAxOSdBdlx1MDAxYVx1MDAwMSYkXCJcdTAwMDNcdTAwMGVDXHUwMDAyZ3Z2blhcdTAwMDFcdTAwMTdZXHUwMDFhXHUwMDA0L2ldW01cdTAwMWE4XHUwMDBiJi9cdTAwMWJcdTAwMGY/ZylcdTAwMWE6aV1aUVxyaWNlXHUwMDA3XHUwMDAyKSxMSkx+XHUwMDEwOkJNXHUwMDFhOFx1MDAxYig2XHUwMDFiXHUwMDA0XHUwMDE3WVx1MDAwZjI3JjhcblxyVHN1cnJDRHhROFx1MDAxNT0/N1xuXHUwMDA2XXN1d25YXHUwMDA0M1ZcdTAwMGZcdTAwMTQ3JEVRSWNcZmZrYFx1MDAxMyU7Slx1MDAxYVx1MDAwZmRpXVtNXHUwMDFhOFx1MDAwMiY6P1x1MDAxMCpMWlRseVdHQ1FcdTAwMTJcYlx1MDAwNS1cdTAwMDIpN1dcdTAwMWRcdTAwMThcImldW01cdTAwMWE+PS5cdTAwMWRcdTAwMWVccilbSkxke1NTTVx1MDAxYSE9KDIxXHIqTEpMflx1MDAxMDpCTVx1MDAxYThcdTAwMWMkKjVcdTAwMGU8XVx1MDAxYVRse0tJXGJ1MChcdTAwMDMnXHUwMDFjN1x1MDAxYlRcdTAwMDRUbFx1MDA3ZlVfTVx1MDAxYThcZlx1MDAwMFx1MDAwMFx1MDAxNVxmI3lcdTAwMDVcdTAwMTkjJVx1MDAxM0lbXGJ9bVx1MDAwNi5cdTAwMTY6M1xcXHJcdTAwMDR0cU8wPFx1MDAxMX1tLlx1MDAxMVx1MDAwZVx1MDAxYVx1MDAwNXlcdTAwMDRcdTAwMWF0cVZfUVx1MDAxNHNcbj8yMFx1MDAxZlx1MDAxOFlcdTAwMWJcdTAwMTN0cVZbUVxiYVx1MDA3ZndySlh2XHUwMDFhXHUwMDBlXHUwMDE3NCpcYklbXHUwMDEwXG5cdTAwMTJublhcdTAwMDFcdTAwMTJISkxnfV9fTVx1MDAxYThcdTAwMTUvN1x1MDAxYlx1MDAwNlx1MDAwMFBcdTAwMDFUbHpLSVxiez49XHUwMDE4XHUwMDAzXHUwMDE2XHUwMDA0eFx1MDAwMllBZ2dFXHUwMDAyMlU4Oy8xXHUwMDExXHUwMDAxeFx1MDAwMlhadFwiJVx1MDAwZVx1MDAwMEslXHUwMDFjLCtISmBcYkRUP1xmXGJcdTAwMDRcdTAwMDVWNDw0YEBZalxyXlp0Klx1MDAwYlx1MDAwNz5LOiYrLlx0SmBcdTAwMTAzVGdyUUlbXHR9bXR2QlhuXHUwMDFhUkd6aVVaV1x1MDAxYWt7cm5YWWpcdTAwMGVKTGd4V0dDXG5gfmV4SFh2XHUwMDFhWUZjaV1aUlxifW12dEpKYFx0RFRnfFNJW1x0fW11c0pKYFx0XVp0eldcXENcdTAwMDJgfHduWFpqXHUwMDAxSkxlfUtJUFx1MDAwZmFtfXNWSmtcYlBUbHpUW01cdTAwMWFkfXdxSEpgXHREVGd7XklbXHRiXHUwMDdma2BIWWhcdTAwMWFSRGZnRVpUXHUwMDAwc3V0blhZbFx1MDAwZkpMZ2dFXlNcYmJ+ZXhLRHhcdFlGdHFWWFFcdTAwMTRzenVyS154XHUwMDAyWVp0el5SQ1x1MDAwMmBjZXNDX3hcdTAwMDJZWnR4U1NRXG5zdXZuWFlrXHRKTGdnRVpYXHUwMDAwc3V2blhZbFx1MDAwMUpMZ2dFWVFcbnN1dHdWSmhcYllUbH5XR0NcdGZ2ZXhLRFx1MDAwN1x1MDAxMURUP3ghXHUwMDA3XHUwMDE4dCdtfXJWSjN0XHJcdTAwMTckJSRcblx1MDAxMlBzdXJ3SFtiXHUwMDBiRFQ8XCJcdTAwMWVcdTAwMWVcdTAwMDBWc3V3blhcdTAwMWQpXVx1MDAxYVx1MDAxOCMmRVFVXG5ifHZ3Tlxcdlx1MDAxYVx1MDAwMTMuO1x1MDAxMzhcblFibX11Vkoza1x1MDAxOFx1MDAxM1x0XG5cdTAwMGJcdTAwMDdDXHUwMDAyZntwblhcdTAwMDFcbldcdTAwMDFcdTAwMThcImldW01cdTAwMWE4XHUwMDFjMi87XHUwMDA1NU1cdTAwMDZcdTAwMDJ0cV9HQ1FcdTAwMTk/XHUwMDE4XHUwMDA3XHUwMDFjXHUwMDBleFx1MDAwMllAbnJLSVxiXHUwMDdmIy4jJ1hSa1xuUVp0XCIlXG5cdTAwMDVWNDw0YEBYdlx1MDAxYVx1MDAwN1x1MDAwM1wiL1xiXHUwMDA0XHUwMDEzZz0qMSdcdTAwMTZKYFxiRFQ/XHUwMDA2XHUwMDE3NCxZKW19dU5adlx1MDAxYVx1MDAwMTI5LzgqXHJUc3Vwd01EeFEpXHUwMDAyXCJcdTAwMTQmXHUwMDA3XHJcdTAwMWFreHRyVkoza1x0XHUwMDAwPyVcdTAwMDBJW1xifW0uXHUwMDA3XHUwMDAyXHUwMDE4LmtcdTAwMDNcdTAwMWZkaV1bTVx1MDAxYTInJixcdTAwMWRccilbXHUwMDAwVGxjXHUwMDFjXHUwMDE2SFx1MDAxNHMsKC9cdTAwMTdcdTAwMWRcdTAwMDVWXHRcdTAwMWIzaV1bTVx1MDAxYThcdTAwMDImOj9cdTAwMTAqTFtUbHlXR0NRXHUwMDEzKiYxXHUwMDBlOzFRXFxUbHtLSVx1MDAxMk08XHUwMDEwXCI6XG5KYFx1MDAwMURUXCIkXHUwMDEzXG5ccmc5IDUxXHUwMDFmSmBcYkRUP1x1MDAwNlx1MDAwNlx1MDAxMyRAITt2YEBaalx1MDAxNEpcdTAwMWZcdTAwMDM7XCJcdTAwMTNcdTAwMTFcdTAwMWFrenVxSFpvXHRYWnQ4XHUwMDBmXHUwMDBlXHUwMDBmSThcdTAwMTA+J1x1MDAxNlx1MDAwNDVPSkx0aUtJXHUwMDA1WSUuKSUlXHUwMDBlP1lcdTAwMWNUbHlfUlJcdTAwMTRzPDAtXGJcZlx1MDAwNUtcdTAwMGJcdTAwMTkkLkVRUVx1MDAxNHNcIigwXHUwMDFmNztMXHUwMDFjXHUwMDA0dHFPMENZJTs1MVhSckNALXRcIlx1MDAwM1x1MDAxM0NcdTAwMDJgfmtgXHUwMDE2XHUwMDFleFx1MDAwMlhaXHUwMDBiYktDOlx1MDAxYTgrP2BAXnZcdTAwMWFcdTAwMDRcdTAwMDB0cVdHPFx1MDAxMX1nXHUwMDFjYFx1MDAxM1xmXCJcdTAwMWFSQnppXHUwMDBiXHUwMDFkQ1x1MDAwMmFjXHUwMDFha1ZAXHUwMDAxXHUwMDFhXHUwMDAxXHUwMDEyLmldWU1cdTAwMWE9OWV4SkRcdTAwMDdcdTAwMTFEXlxyaVx1MDAwZVx1MDAwZlx1MDAxOVx1MDAxYWt+dW5YXHUwMDA0LFx1MDAxYVJGelx1MDAxNk5HSWNzJiM6WFJrXHUwMDE0Slx1MDAxYSBpXVtNZXhjb1x1MDAxOVhcdTAwMDE+QEpMZWdFXHUwMDA3XHUwMDE3XHUwMDFha1x1MDA3ZmtcdTAwMWZTRHJjSlx1MDAxZjIzRVFQXGJ9bSs0WFJqXHUwMDE0NV96YzxJXGJcXCltfXdWSjZOSkxmZzpCTVx1MDAxMFxubS4mXHUwMDAySmBcdTAwMDBEVDo9RVFRXHUwMDE0XGZma2ohSjNcXFx1MDAxMFRscktJXHJOc3V3bidBdlx1MDAxMDNUPy9cdTAwMWZJW1x1MDAwZn1tKzRYUmpcdTAwMTQ1X3pjPElcYlxcKW19c0lEeFRcdTAwMWVUbHxSXFxNZXhjb1x1MDAxOVhcdTAwMDE+QEpMZ1x1MDA3ZktJXHJOc3VzcE5EXHUwMDA3XHUwMDExRFx1MDAwYlx1MDA3Zmc6Qk1cdTAwMWE4KyUrXHUwMDFlNz5dXHUwMDFiXHUwMDE1dHFPXHUwMDEwXHUwMDFjXHUwMDExfW1cdTAwMDYuXHUwMDE2Oy9VXHUwMDA1XHUwMDE5OGldQ1x1MDAxYVx1MDAxMFxubS5cdTAwMTBcdTAwMWZcdTAwMWJcdTAwMDVZXHUwMDA0XHUwMDFhdHFVXU1cdTAwMWE9LjQ2XHUwMDE5XHUwMDAwP1tcdTAwMDNcdTAwMDUjKVx1MDAxZFx1MDAxMUNcdTAwMDJjXHUwMDdmdntWSjN1XHUwMDE4VGx+UEdDVDguKTFcdTAwMTJcdTAwMDcvXHUwMDFhUkZ6aVx1MDAwM1x1MDAwNFx1MDAwNVx1MDAxYWt+dnZORHhZXHUwMDFjXHUwMDAyXHQ5XHUwMDA2XHUwMDFmXHUwMDA0XHUwMDFha1x1MDA3ZmtgXHRcdTAwMWQ3VVx1MDAwN1x1MDAxOFx0KFxiXHUwMDA3XHUwMDBlSnN1d25YXHUwMDAxXHUwMDFlXVx1MDAwZSlcdTAwMTcnXHUwMDBiSVtcZmVjZTBcdTAwMGZcdTAwMTEzXFxcdFx1MDAxOHRxV0dDUVx1MDAxYy4gXHUwMDA2XHUwMDFmXHUwMDBlXHUwMDA1WVx1MDAwNFx1MDAxYXRxVFpNXHUwMDFhOFx1MDAwMiYlJVx0NlRKTGdcdTAwN2ZLSVxifDQ3XHUwMDE4XHUwMDAzXHUwMDE2XHUwMDA0eFx1MDAwMlxcR3ppXHUwMDE0XHUwMDFlXGZVPiFcdTAwMTgnXHUwMDBiXHUwMDFkM0hcXCkyLlx1MDAxNFxiQ1x1MDAwMnNta2BcdTAwMTMpLkw3MHRxX0dDSyRcIiotXHUwMDE0NzlXXHUwMDFhXHUwMDEzdHFPMDxcdTAwMTF9bS0rXHUwMDE0XHUwMDAyM11KTH5cdTAwMTBFXGJcdTAwMGVKNG19aiE1c1x1MDAxNEpcdTAwMTU4P0VRUVx1MDAxNHMjP2BAWHZlQVp0XHUwMDAzNzQseVx0bX13T1hqXHUwMDE0Slx1MDAxMSQkXHUwMDEwSVtcdGF4cm5YXHUwMDBiKVlcdTAwMWVcdTAwMTMsMUVRQ1x0Y353PktablxuXHUwMDE0R2RcdTAwN2ZUXHUwMDE3UFx0ZXs7cUJdakRaRmVcdTAwN2ZFR0NfIyAwNlx1MDAxMiU7QEpMZ3tUW01cdTAwMWE4XHUwMDFiPjJcdTAwMWZKYFx0WERme1NHQ1FcdTAwMTYqKStcdTAwMGZcdTAwMWJ4XHUwMDAyWFp0KFx1MDAwNlx1MDAxOVx1MDAxM0E2PSYmXHUwMDFmXHUwMDEyIFx1MDAxYVJGemlcdTAwMGUqXHUwMDE1TFx1MDAwZS4rLlhSaFx1MDAwMURUNz9cdTAwMTNJW1x0Y353blhcdTAwMDUqXHUwMDFhUkRmeFNHQ0s7KGV4SkR4azgyXHRcdTAwMDYmM0NcdTAwMDJgenJyVkojTVx0XHUwMDE4LlwiXHUwMDA2XHUwMDA0Q1x1MDAwMmFjZSspXHUwMDFjKGdcdFx1MDAxYTppXVpZXHUwMDE0cyZcbjIlXHUwMDA1O0BKTGN8S0lcYnAhbX1zTF12XHUwMDFhXHUwMDAxJSYuOFxuXHJUc3V0cVZKM3pcdFx1MDAxOTQqXGJJW1x0fW0mLlx1MDAxNjcpU1x1MDAwMVx1MDAxYTo4RVFJY3N8d3dYUmtcdTAwMTRKQmd8RVFQXHUwMDE0XGZma2BcdFx1MDAxOD9cdTAwMWFSR2RcdTAwN2ZUR0NRXHUwMDEyIDVcdTAwMWRcdTAwMWJcdTAwMDQ2XHUwMDFhUkRiZ0VcdTAwMDIxVzghM2BAWW9cdTAwMTRKXHUwMDA3PypcdFx1MDAwMVxiVj06ZXhKRHhRIFx1MDAwNlx0Jlx1MDAwNlx1MDAxM0NcdTAwMDJgeXJuWFx1MDAwMVxiXVx0XHUwMDFhXHUwMDE1JFx1MDAwYlx1MDAwNFx1MDAxM1x1MDAxYWtcdTAwN2ZrYFx1MDAxMy8oWVxmXHUwMDEzdHFUR0NbPj1cIlx1MDAxZFx1MDAxOVx1MDAwNDVLXHJUbHtLSVxyXTc7XHUwMDE4M1x1MDAxNlx1MDAxMDZcdTAwMWFSQXppXHUwMDBlL1x1MDAwZVxcXHUwMDBlXHUwMDBlKy5YUmlcdTAwMGZEVFwiJlx1MDAxNzRcclE/KD8rXHUwMDE0XHUwMDBmeFx1MDAwMlhadCdcdTAwMGVcclx1MDAwNFx1MDAxYWt2dXZNRHh5PD1cdFx1MDAwNiYzQ1x1MDAwMmB6cnJWSjJISkxlc1JbTVx1MDAxYVwiOiovXHUwMDE1XHUwMDA2XHUwMDA1XVx1MDAxOVx1MDAwMz87UzRcdTAwMTVBISpleEpEeFxcXHJcdTAwMTB0cVZZVVxufW1cdTAwMDNcdTAwMDc8N1x1MDAxN3kwVGx6Ul5RXHUwMDE0c1x1MDAwMlx1MDAxNFx1MDAxZDcpXHUwMDAyXHUwMDFhUkdue1dHQ3VcdTAwMDFcdTAwMTBcblx1MDAwM1wiSmBcdTAwMGJYQ2ZnRVx1MDAwMVx1MDAwYmc0NzMwXHUwMDFiNztcXFxmVGx7S0lcYnI7XHRcIidcdTAwMWUrPlx1MDAxYVJGelx1MDAxNk5HSWNzJlx1MDAxNSdcdDc7VFx1MDAwNFRsel9HQ1QwPDMhXHUwMDEyXHI5U1x1MDAxYlx1MDAwMzQxXHUwMDFkSVtcbmF+fm5YXHUwMDAxXHUwMDE3SEpMYn5LSVxyUTAhNCpcdTAwMTVcdTAwMWR4XHUwMDAyWFp0L1xiXHUwMDBmQ1x1MDAwMmBcdTAwN2Z1dFZKO0xcdTAwMWMpJCpcdTAwMTNcdTAwMGVDXHUwMDAyYWNlMVx1MDAwZlx1MDAwNTdXXHUwMDA2KTUkXHUwMDBiXHUwMDA0XHUwMDEzXHUwMDFha1x1MDA3ZmtgXHUwMDEzLD9eNzc6J0VRU1x1MDAwZn1tNTdcdTAwMDNcdTAwMDE+WVx1MDAwNlRse0tJXGJ1MChcdTAwMDMnXHUwMDFjNztUXHUwMDA0VGx5UEdDUVx1MDAxYy4gXHUwMDFkXHUwMDFiXHUwMDA0Nlx1MDAxYVJHZWdFXHUwMDAyJV0pXHUwMDEwXHUwMDA2Llx1MDAxNkpgXHUwMDBiWVp0OFx1MDAxMlx1MDAwNlxmVz9cdTAwMTBcIjNcdTAwMGZcdTAwMDEqXGY3XHUwMDEyMzhcdTAwMDRJW1x1MDAxYXNjZSs7XHUwMDFjLmcuVGx5S0lcdTAwMTJNPFwiKCwlXHUwMDBiNUpcclRsYzw2SFx1MDAxNHMlLixcdTAwMTBcdTAwMDE/XHUwMDFhUl5ccmlcdTAwMDRcdTAwMDRcdTAwMTNdc3VvXHUwMDE5J0F2XHUwMDFhXHUwMDBiXHUwMDE4XCJpXVtNXHUwMDFhPTdleEpEXHUwMDA3XHUwMDExRFRcdTAwMWVcdTAwMWI4JiBgc3Vyd0pYdlx1MDAxYVx1MDAwZlx1MDAwNDk8RVFQXHRnfmtgXHUwMDE5XHUwMDFiO05cclxmLGldSVBcdGNcdTAwN2Y7c0tcXGpEWUJnfVx1MDAxYlpRXG5nM3NyQ10mXHRfRG5pS0lcdTAwMDZKPjgzKjdcdFwiXHUwMDFhUkdnc1NHQ1FcdTAwMDU2NydYUmtcYlpGZHhLSVxiXHUwMDdmNCEuN1x0SmBcYkRUNSpcdTAwMTVcdTAwMTlcdTAwMThfIy4jJ1x1MDAwMFx1MDAxMnhcdTAwMDJYWnRcIiZcdTAwMWZcdTAwMTVnMCMrYEBaalx1MDAxNEpcdTAwMTdcIj9FUVBcdGNcdTAwN2ZrYFx1MDAxN1x1MDAxOHhcdTAwMDJZQWRzS0lcdTAwMTJSNm19clZKXHRoLClcdTAwMWJcbj9JW1x0ZHp3blhcdTAwMTEvWVx1MDAwNlx1MDAwZT8qXGJJW1xifW0uXHUwMDExXHUwMDBlXHUwMDFhXHUwMDA1WVx1MDAwNFx1MDAxYXRxVlNNXHUwMDFhOFx1MDAwMjdcdTAwMWRcdTAwMTdcdFwiXHUwMDFhUkJjZ0VcdTAwMDIpSHN1dXJIRHhRO1x1MDAwNjNcdTAwMTRcdTAwMDZcdTAwMDdcclx1MDAxYWt9dW5YXHUwMDAxXHUwMDE4WVx1MDAwN1x1MDAxNDckRVFQXHUwMDE0cy4rLiVcdTAwMWIxUVx1MDAwNFx1MDAxYSVpXUM6XHUwMDFhZXx3YEBZdlx1MDAxYVtEYGldWk1cdTAwMWFkXHUwMDdmdWBAWXZcdTAwMWFbRmBpXVpNZXhjZTFcblxyeFx1MDAwMllCZ31LSVxiez49XHUwMDE4I1x1MDAxNlx1MDAwNHhcdTAwMDJaT3ppXHUwMDBlO1x1MDAwZVE/O2V4SkR4SVx1MDAwMVx1MDAxNzghXHUwMDBlXHUwMDA1XHJNc3V3blhcdTAwMDFcdTAwMTJIN1x1MDAxYjczRVFTXGJjY2UrKFxyO1QrXHUwMDE5OiRcdTAwMTVJW1xifW0uXHUwMDA1XGJcdD5dSkxmZ0VcYlx1MDAwZUo0XHUwMDEwJC5cdTAwMTVcdTAwMWI/XHUwMDFhUkZ6aVx1MDAwYlx1MDAwZVx1MDAwN0xcdTAwMGU+KzpcdTAwMTZKYFx1MDAwZkRUP1x1MDAwZlxiXHUwMDBmPnk9I2V4SFp2XHUwMDFhXHUwMDFjXHUwMDFiJlx1MDAxNFx1MDAwYlx1MDAwMlx1MDAwZl8pJiklWFJqXHUwMDE0Slx1MDAxYT8tXHUwMDAySVtcdGF7cnJWSlx1MDAxYmwjKVx1MDAxYlxuP0lbXHRkenduWFx1MDAwMCpcdTAwMWFSQmZyUkdDSyRcIiotXHUwMDE0Nz9JXHUwMDFkXHUwMDFmJlx1MDA3ZjhcdTAwMWZcdTAwMThING19clZKPl1cdTAwMGVUbHpWX1FcdTAwMTRzXHUwMDBiXHUwMDAyXHUwMDA0JSVcdTAwMWJgSkxnflJbTVx1MDAxYVx1MDAxY1x1MDAxY1x1MDAxOFx1MDAwZjsweFx1MDAwMllOZntLSSxoXHUwMDBlXHUwMDAyXHUwMDA2XHUwMDFhWFJpXGJdRnppXHJcdTAwMDE+XSk7NSMlXHQ+XFxKTGZnRVx1MDAwMitSXHUwMDE3KlwiJjlcZnhcdTAwMDJYWlx1MDAwYmJLXHUwMDE2SFx1MDAxNHMmXG4jXHUwMDAyLVwiSFx1MDAxY0J0cVVbTVx1MDAxYVwiJ1wiLFx1MDAwYlx1MDAwMVx1MDAwNUhcdTAwMDdcdTAwMDV0cU9cdTAwMTBRXHUwMDE0YWM6a1ZKXHUwMDFiVFx1MDAwNDMnPlx1MDAwZVx1MDAxYkNcdTAwMDJ5XHUwMDE0dnhSM3hRPFx1MDAwZiYuRVFTXHJgeGtgXHUwMDE5LD9LXHUwMDBiVGxpRFx1MDAxOVx1N2IyOFx1N2U5ZnF4d2JaSyhcdTliNmNcdTZjYmRWfXxXS1x1OTY1M1x1NWY5OXFkdHtZXHUwMDFhXHU4MDRhXHU0ZTdkXHU1ZWNlVmV5Vkg4XHUwMDE4cW1rXHUwMDFmU0RiXHUwMDAyQC10XCIzXHUwMDEyXHUwMDExXXN1dXRLX3ZcdTAwMWFcdTAwMGIyMzhcdTAwMDRJW1x1MDAxYXI9XHU3YjBlXHU3ZWU1Wl9qXHUwMDE4SFx1NGVlMlx1ODgxYWtcdTU3NzhIXHUwMDEzXHUwMDFiI1x1NmM1Ylx1ODgwN2JRUGpcdTAwMThcdTk2NWFcdTVmZDd2YFZbVlx1MDAxYiNcdTgwNWZcdTRlMDJcdTVlZTRaWm9cdTAwMDBIVlx1NGZiOFx1NzQ0ZFx1NTk1Nlx1OGQ0ZUFcdFx1NmI3MGw1XHU5NTc5XHU3MGM2XHU3YjIxXHU3ZWZkXHUwMDE4WlZ2XHU5NTNkXHU1ZDJiXHU1YmY2XHU3NzkyXHUwMDE4XHU1MTE4XHU4MmRkXHU3N2I0YVxiS1x1MDAxZFx1MDAxYi9cdTRmMjVcdThkN2VrTFpTXHUwMDFiXGJsXHUwMDFlYlpKdmVBWmJxTzBDUVx1MDAwNTY3J1hSaFx1MDAwMFhAemlcdTAwMDQvXHUwMDA0SzJtfWBZXHUwMDFhXHU3YjEzXHU3ZTlmSEJma0dIXHUwMDEzXHU3MDRkXHU1MmNhb2xxTksoXHU4MDI4XHU0ZTJkXHU1ZWQwdnpXWEJhcj1kIU4sXHUwMDE4eS5CXHU3MjJmXHU2NTAzXHVmZjdkSFx1MDAwMlxmXHUwMDE1XHJcdTAwMDZcdTAwMDROXHU0ZTdiXHU2Y2IyXHUwMDFiMVZ2aUs2SFx1MDAxNGd1b1x1MDAxOVhcdTAwMDFcdTAwMGVBXHUwMDE4XHUwMDEzdHFWWFRcYn1tJFx1MDAwNlx1MDAxZlx1MDAxYjlcdTAwMWFSVHU5XHU3YjJlXHU3ZWNjQVx0YVx1MDA3ZmdiXHU0ZWVlXHU4ODI0elx1NTcyN0tcdTAwMDR1OVx1NGY0M1x1NWJkOEFcdTAwMTNie3ZiXHU1NDA3XHU0ZTQ1elx1MDAxM1tBbmhcdTAwMTVcdTgwN2JcdTRlMjRcdTVlOWVxeWQwXHU5NTQxXHU3MGQ0XHU3YjEzXHU3ZTlmSER2a1x1OTUxMVx1NWQyN1x1NWJmY1x1NzdjYnFcdTU5NjVcdTk2NzRcdTc3YjFZXHUwMDFheVx1MDA3ZksxXHU4MDQ2XHU1MmQwR0BQXHUwMDBmclx1MDAxNmRcdTAwMWJZXHUwMDFheW9cdTUyNWVcdTkwNTZcdTgwNTNcdWZmNTEoJFFcdTViYzNcdTI1ZjFcdTY4ZTlcYlxyNVx1NWY1Mlx1NTM0Y1x1NjI2Ylx1OTA0OFVcdTAwMGZrR0lNZXhjXHUwMDFha1ZKM2tcdTAwMWRcdTAwMWJcdTAwMTcmXGJcdTAwMWVcdTAwMGZMXHUwMDE0N2V4SkR4cFxyXHUwMDA0OVx1MDAxOFx1MDAwNFx1MDAwNFx1MDAxM11zdXZ1VkouV1x1MDAxY1x1MDAxNzpcdTAwMTRcdTAwMDZcdTAwMWRcdTAwMDBMMD1leEpEeFFcdTAwMGJcdTAwMTk6JFx1MDAxNTRcdTAwMDRAc3V3bidBIn0=@")));
console.log(role_info);
return role_info;
}

function js_eval(js_str) {
return eval("(" + js_str + ")");
}

function lpc_2_js(lpc_str) {
var convert_dict = {
"([": "{",
"])": "}",
",])": "}",
"({": "[",
"})": "]",
",})": "]"
};
function convert($1) {
var match_str = $1.replace(/\s+/g, '');
return convert_dict[match_str];
}
var parser = new RegExp("\\(\\[|,?\s*\\]\\)|\\({|,?\\s*}\\)",'g');
return lpc_str.replace(parser, convert);
}


function decode_desc(ciphertext) {
if (ciphertext = ciphertext.replace(/^\s+|\s+$/g, ''),
!/^@[\s\S]*@$/.test(ciphertext))
return ciphertext;
var _0x36ab38 = "";//(/\b_k=([^;]*)/.exec(document.cookie) || [])[0x1] || '';
if (ciphertext = ciphertext.replace(/^@|@$/g, ''),
/^[^@]+@[\s\S]+/.test(ciphertext)) {
var num = ciphertext.indexOf('@');
_0x36ab38 = ciphertext.substring(0, num),
ciphertext = ciphertext.substring(num + 0x1);
}
debugger;
var _0x1b3f48 = function s(ciphertext) {
try {
return window.eval('(' + ciphertext + ')');//
} catch (_0x40b9c3) {
return null;
}
}(ciphertext = window.atob(ciphertext));//解码
_0x1b3f48 && 'object' == typeof _0x1b3f48 && _0x1b3f48['d'] && (_0x1b3f48 = _0x1b3f48['d']);//从对象{'d':'xxx'} 取到xxx
var str=_0x1b3f48;
//numList 是二进制数字的集合
for (var numList = [], j = 0, i =0; i < str.length; i++) {
var charCode = str.charCodeAt(i)
, _0x341952 = _0x36ab38.charCodeAt(j % _0x36ab38.length);//_0x36ab38 是一个短的字符串 如 QOGBzhZ8hvVKgka8
j ++,
charCode = 0x1 * charCode ^ _0x341952,
numList.push(charCode.toString(2));
}
return function d(ciphertext) {
for (var arr = [], i = 0; i < ciphertext.length; i++)
arr.push(window.String.fromCharCode(window.parseInt(ciphertext[i], 2)));
return arr.join('');
}(numList);
}

另外附上依照此js写的java版本(仅核心代码,其他缺失部分可以自己手动填加)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private static String decodeStr(String ciphertext) throws UnsupportedEncodingException, ScriptException {
// 去除前后空格,判断先后字符是否符号特定规则
ciphertext = ciphertext.trim();
if (!(ciphertext.startsWith("@") && ciphertext.endsWith("@"))) {
return ciphertext;
}
ciphertext = replace(ciphertext, "^@|@$", "");
// 将字符串分成两部分
int index = ciphertext.indexOf("@");
String ciphertextPrefix = ciphertext.substring(0, index);
String ciphertextSuffix = ciphertext.substring(index + 1);
// 对ciphertextSuffix解码
ciphertextSuffix = BtoAAtoB.atob(ciphertextSuffix);
Object ciphertextSuffixObj = evalJS('(' + ciphertextSuffix + ')');
ciphertextSuffix = JSONObject.toJSONString(ciphertextSuffixObj);
JSONObject jsonObject = JSONObject.parseObject(ciphertextSuffix);
// 从对象{'d':'xxx'} 取到xxx
ciphertextSuffix = jsonObject.get("d").toString();
// 转二进制
List<String> numList2 = new ArrayList<String>();
for (int i = 0, j = 0; i < ciphertextSuffix.length(); i++) {
char charCode = ciphertextSuffix.charAt(i);
char charCode2 = ciphertextPrefix.charAt(j % ciphertextPrefix.length());
j++;
int charCodeInt = 1 * (int) charCode ^ (int) charCode2;
numList2.add(Integer.toBinaryString(charCodeInt));
}
// 转字符串
String byteArrayStr=listTobyte2(numList2);
System.out.println("--------------");
return lpc_2_js(byteArrayStr);
}

java基础知识点归纳

发表于 2019-10-01

统计了java的知识点,后面的有些自己也没有接触过,需要一步步学习,后期会将学习的东西补充上来


基础

  1. 数据类型与字长
  2. switch语句
  3. index for 和foreach
  4. labeled loop
  5. 异常体系
  6. 集合体系结构
  7. 迭代器
  8. 集合和泛型

强化

  1. LinkedList
  2. ArrayList
  3. HashMap
  4. TreeSet
  5. Quene
  6. WeakHashMap
  7. 集合只读视图
  8. 集合同步视图
  9. deprecated集合
  10. 线程体系结构
  11. 线程状态转换
  12. valatile
  13. Atom对象
  14. deprecated线程API
  15. File对象
  16. thread local对象
  17. input/output流设计体系
  18. 字符编码设置
  19. NIO
  20. 正则表达式
  21. 反射体系结构
  22. 类初始化过程
  23. classloader层次结构设计

进阶

  1. 有向图/根节点
  2. GC原理
  3. finalized和GC
  4. java安全类库
  5. SQL注入
  6. JDBC
  7. socket
  8. URL和URI
  9. 资源状态错误原理
  10. JDK工具
  11. 泛型集合协变
  12. 优先级Quene
  13. stream与MapReadnve
  14. Collections/Arrays/Commons
  15. 线程中断
  16. 线程/线程组默认处理机制
  17. Callable/Future
  18. 线程池/定时器

了解

  1. Semaphore/CountDownlatch/CyclicBarrier
  2. JNI:java层与C层数据双向访问
  3. JNI:java层与C层数据双向调用
  4. jNI库生成/加载机制
  5. SecurityManager
  6. java二进制保护
  7. JDBC参数调优
  8. 数据库连接池参数调优
  9. JIT机制
  10. 典型Carbage Collectors原理
  11. GC参数调优
  12. socket与ososI协议栈资源管理
  13. java层线程/C层线程/OS线程/CPU核(物理线程)关系
  14. class格式
  15. 栈帧结构
  16. klass-oop

AK/SK认证方式

发表于 2019-08-22

AK/SK认证是对请求消息按照一定规则生成签名信息,服务器对签名信息进行安全认证,主要作用是保证请求的可靠性,完整性。

ak表示公钥,sk表示私钥。ak与sk一一对应,不同的域使用不同的aksk.

下面提供一个简单的签名认证方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class AKSKImpl {

private static String AK="123456789";

private static String SK="012345";

public static void main(String[] args) throws Exception {
String str= sign("1234.do","11111111","11111",AK,SK);
System.out.println(str);
}

private static String sign(String url,String dateTime,String numNoice,String ak,String sk) throws Exception{
String data= ak+url +numNoice+dateTime;

String sign=hamcsha1(data.getBytes("UTF-8"),sk.getBytes("UTF-8"));

return sign;
}
public static String hamcsha1(byte[] data, byte[] key)
{
try {
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
return byte2hex(mac.doFinal(data));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//二行制转字符串
public static String byte2hex(byte[] b)
{
StringBuilder hs = new StringBuilder();
String stmp;
for (int n = 0; b!=null && n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1)
hs.append('0');
hs.append(stmp);
}
return hs.toString().toUpperCase();
}
}

新公司的体验

发表于 2019-04-09

新入职公司快两个月的时间了,中间因为搬家还有入职后的乱七八糟的事情,感觉周末过的一直不怎么舒服。现在抽出点时间来记录下新公司与之前公司的区别。

  • 新公司比以前公司要累很多(事情多,没人带,新东西没人教,很多人推三阻四),以前的公司以业务为主,能实现就行,新公司的要求更高,代码质量,文档,需求确认,安全,
  • 新公司的流程更加规范,体现在代码提交规范,业务开发流程,测试流程,提交各种电子流流程(请假,转正,补签到等)。虽然刚开始可能会不习惯,弄着弄那的觉得很烦,但是因为流程规范,实施起来是绝对遵从的(比如年假制度,工资发放,调休制度)。
  • 除了上班时间,下班离开公司后很少烦你。
  • 与大佬接触的更多,可能学到的东西更多。
  • 能专注于java后端,前端服务器维护这些不用再了解过深,有更多的时间去钻研一个方向。
  • 开发的产品是绝对有市场需求的,不会突然暴死,遇到的实际问题更多,对自己成长有益。
  • 团队更大,有助于增加协作经验。

    希望自己能在这里发展的更好。

1…567…10
无恤

无恤

java博客

95 日志
7 分类
29 标签
GitHub
© 2018 - 2021 无恤
本站访客数:人次
本站总访问量次