[go: up one dir, main page]

2012年

JSONKit杂记

记录

写程序时遇到的几个问题,记录一下。

  • 加到project里面的时候不能加在子目录下
  • 编译的时候需要指定JSONKit.m的compiler flags "-fno-objc-arc"

吐槽

object-c的函数长度真心是伤不起的,截图留念!

sublime text2 svn sftp plugin keygen

第一次写object-c程序,写了好几个小时才写出来这么个小东西。

  1. 反编译pyc文件,查看算法
  2. 写出key生成的算法
  3. 将python嵌入Object-C,得到最终的程序

将email和生成的key写入插件目录下的sublime-setting文件。

"email": "your email",
"product_key": "the key",

下载地址:svn-sftp-keygen.app.zip

2013-03-19 增加 邮件获取注册码

发送任何邮件到 bot[at]tool.lu, 系统会自动生成注册码,并回复到你的发件邮箱

2013-04-24 增加 osx10.7支持,优化算法机

QQ20130424-1.png
下载地址:svn-keygen.app.zip

mac chrome下input submit样式

input submit指定样式不起作用

QQ20121209-1.png

There will be three new appearance constants for buttons. They are push-button, bevel-button and button. input will be using push-button by default. This constant maps to the Aqua system button. When this appearance constant is specified, the only way to disable the Aqua look will be by setting the appearance constant to none (which will give you a completely blank slate on which to build your own button look) or by specifying your own background and border properties. Specifying the background/border will result in the Aqua appearance being disabled and a more platform-neutral look being used.

来自:https://www.webkit.org/blog/28/buttons/

解决办法

/* 指定border或者background就可以了 */
input[type=submit] {
	border: 1px solid #CCC;
	/* background: red; */
}

自动禁用连接数高的IP

python代码

由于最近服务器受到大流量的攻击,于是写了该脚本。

#! /usr/bin/env python
# encoding: utf-8

import os, time

command = "/bin/netstat -antp|grep :80|awk ' ''{print $5}'|awk -F: '{print $1}'|sort -r|uniq -c|sort -n -k1 -r"
maxconn = 150

handle = os.popen(command)
for line in handle:
	fields = line.strip().split(' ')
	if len(fields) != 2:
		continue
	conn, ip = fields
	# 由于我们使用的是nginx作为反向代理,访问apache,所以这里要加上127.0.0.1
	if int(conn) > maxconn and ip != '127.0.0.1':
		print(time.strftime('%Y-%m-%d %X'), conn, ip)
		# 这里只会临时将ip拒绝,当重新启动iptables服务的时候失效
		os.system('/sbin/iptables -I INPUT -s %s/24 -j DROP' % ip)
handle.close()

定时执行

将python文件加入crontab中即可。

SimpleIni修改my.cnf

为了实现自动化修改mysql的配置文件,使用C++程序对改ini样式的文件进行修改

#include "SimpleIni.h"
int main(int argc, char* argv[]) {
	CSimpleIniA ini;
	const char* filename = "/etc/my.cnf";
	ini.SetUnicode();
	ini.LoadFile(filename);
	ini.SetValue("mysqld", "server-id", "1");
	ini.SetValue("mysqld", "binlog-do-db", "mydb");
	ini.SaveFile(filename, false);

	return 0;
}

使用python Queue创建文档格式转换服务

该项目比较简单,只具备文件排队转换,不具有查看队列的功能,使用openoffice和unoconv作为转换程序,程序不提供建立系统服务

使用场景,一般使用thrift建立服务,将该程序挂载在里面。

#!/usr/bin/env python
#encoding: utf-8
#author: xiaozi <245565986@qq.com>
import Queue, threading, os, subprocess
import time

class Converter(object):
	def __init__(self):
		self._tasks = Queue.Queue()
		self._docs = Queue.Queue()
		self._pdfs = Queue.Queue()

		self._toPdfThreads = []
		self._toSwfThreads = []
		self._toPdfThreadNum = 4
		self._toSwfThreadNum = 4

		self._dispatchThread = threading.Thread(target=self.dispatchTask)
		self._dispatchThread.setDaemon(True)

		for i in range(self._toPdfThreadNum):
			pdfThread = threading.Thread(target=self.toPdf)
			pdfThread.setDaemon(True)
			self._toPdfThreads.append(pdfThread)

		for i in range(self._toSwfThreadNum):
			swfThread = threading.Thread(target=self.toSwf)
			swfThread.setDaemon(True)
			self._toSwfThreads.append(swfThread)
		
		self._dispatchThread.start()
		for i in range(self._toPdfThreadNum):
			self._toPdfThreads[i].start()
		for i in range(self._toSwfThreadNum):
			self._toSwfThreads[i].start()

	def addTask(self, path):
                print(path)
		self._tasks.put(path)

	def dispatchTask(self):
		while True:
			path = self._tasks.get()
			if not path:
				break
			ext = os.path.splitext(path)[1][1:].lower()
			if ext == 'doc' or ext == 'docx':
				self._docs.put(path)
			elif ext == 'pdf':
				self._pdfs.put(path)

	def toPdf(self):
		while True:
			path = self._docs.get()
			if not path:
				break
			subprocess.Popen(
				['python', 'unoconv', '-f', 'pdf', path]
			).communicate()
			newpath = os.path.splitext(path)[0] + '.pdf'
			self._pdfs.put(newpath)

	def toSwf(self):
		while True:
			path = self._pdfs.get()
			if not path:
				break
			# do something
			path_target = os.path.splitext(path)[0]
			if not os.path.exists(path_target):
				os.makedirs(path_target)
			subprocess.Popen(['pdf2swf', path, '-o', path_target + '/page%.swf', '-f', '-T', '9', '-t', '-s', 'storeallcharacters']).communicate()
			print(path)

	def close(self):
		self._tasks.put(None)
		self._dispatchThread.join()

		for i in range(self._toPdfThreadNum):
			self._docs.put(None)
		for i in range(self._toPdfThreadNum):
			self._toPdfThreads[i].join()
		# '转换为pdf'线程都结束之后,再结束'转换为swf'的线程
		for i in range(self._toSwfThreadNum):
			self._pdfs.put(None)
		for i in range(self._toSwfThreadNum):
			self._toSwfThreads[i].join()

if __name__ == '__main__':
	converter = Converter()
	converter.addTask('docs/paper.docx')

	time.sleep(3)

	converter.close()

下面是使用thrift建立的service

#!/usr/bin/env python
# encoding: utf-8

import sys, time

import convert

from thrift.transport import TSocket, TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

sys.path.append('thrift/gen-py')

from ConvertApi import *
from ConvertApi.ttypes import *

class ServerHandle(ConvertApi.Iface):
	def __init__(self):
		self.converter = convert.Converter()

	def addTask(self, path):
		self.converter.addTask(path)
		return True

def main(port = 1990):
	processor = ConvertApi.Processor(ServerHandle())
	transport = TSocket.TServerSocket(port = port)
	tfactory = TTransport.TBufferedTransportFactory()
	pfactory = TBinaryProtocol.TBinaryProtocolFactory()

	server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
	print('Starting server on :%d' % port)
	server.serve()

if __name__ == '__main__':
	port = 110110
	main(port)

thrift文件如下(该接口提供的比较简单):

service ConvertApi {
	bool addTask(1: string path);
}

discuzx模块数据调用

后台 > 门户 > 模块管理 > 数据调用

语法

DIY模块模板语法详解

[loop]...[/loop]标签来循环显示模块中的数据;如果要在模板中多处循环可以使用[loop1]...[/loop1]的方式扩展(只能扩展1-9个)

[order=N]...[/order]标签来替代默认loop中的第N个位置数据的展示,你可以使用[order1=N]...[/order1]的方式来扩展(对应[loop1],只能扩展1-9个)

其中:[order=odd]为奇数行,[order=even]为偶数行
[index=N]...[/index]的方式来指定第N条数据的展示方式,由该语法指定的数据不再在loop循环中出现,可以通过[index1]...[/index1]的方式来扩展(只能扩展1-9个)以实现同一条数据多处展示

实例

[index=1]

{title}

{summary} [详细]

[/index]

Openfire + err

安装Openfire

Openfire是IM的服务器端,下载地址:http://www.igniterealtime.org/downloads/index.jsp,选择linux rpm包下载

rpm -ivh openfire-3.7.1-1.i386.rpm

配置Openfire

首先在mysql里面建立一个数据库openfire,访问9090端口,进入网页进行初始化配置,增加一个用户,下面的err配置的时候会用到

安装err

err是一个IM机器人,项目地址:https://github.com/gbin/err,最简单的安装方法easy_install

easy_install err

建立几个需要用到的文件夹

mkdir -p /var/www/err
mkdir -p /var/log/err
mkdir -p /var/lib/err

chmod -R 777 /var/www/err
chmod -R 777 /var/log/err
chmod -R 777 /var/lib/err

cp /usr/lib/python2.6/site-packages/err-1.6.7-py2.6.egg/errbot/config-template.py /var/www/err/config.py

cd /var/www/err/

# 按照自己的要求修改吧,把上面配置的用户加到这个里面
vi config.py

其他

err.py命令启动的时候,可能还会报其他的模块不存在,直接easy_install好了

关于机器人插件的开发,可以参考项目主页上的wiki

YII修改CGridView默认排序

CSort里面是有一个defaultOrder的属性,但是GII自动生成的CURD不能这么来;后来找到个帖子(Model Search - Merging in a default start criteria),里面写的比较详细。但是他在Controller里面的条件判断需要改下。

$merge = new CDbCriteria;
if(empty($_GET['Depart_sort'])) {
	$merge->order = 'displayorder DESC';
}

主要的流程就是:

  1. 在控制器里面判断用户是否有指定排序字段,若没有则加上默认排序字段
  2. 传变量到模版里,由用户浏览页面,执行search
  3. model里面合并criteria的order条件

PolicyServer

最近做一个项目需要用到websocket,但是目前ie9及之前的版本都不支持,github上面出现了用flash模拟websocket的开源项目,由于使用flash时,flash是有权限限制的(这应该是为了安全性考虑),xmlsocket://会先访问843端口,获取授权文件。于是自己用python写了个,该程序依赖tornado库。http://inote.github.com/PolicyServer/

inotify-tools安装

前提

# 查看内核是否支持inotify机制
grep INOTIFY_USER /boot/config-$(uname -r)

下载安装

# https://github.com/rvoicilas/inotify-tools/
wget ...
tar zxf ...
# 若是没有configure文件,先运行
# ./autogen.sh
./configure --prefix=/usr/local/inotify
make && make install

基础的使用

inotifywait -rme modify,attrib,move,close_write,create,delete,delete_self /etc/asterisk

chrome下固定定位元素在锚点跳转时显示不全

做项目时遇到两次,就纪录下来。(仅在chrome下出现此bug)

产生条件:

  • 1.锚点链接上绑定了点击事件;

现象:

在chrome下测试发现,绝对定位的元素只显示一部分,但是稍微滚动滚动条或者改变窗口大小后又正常了。

原因:

个人觉得:跟浏览器渲染,在点击页面内锚点时触发了默认的跳转锚点的动作和绑定的click事件,两个同时执行后绝对定位元素渲染出bug

解决方案:

  • 1.点击事件内加return false来阻止默认行为;(可行性不高,因为阻止了锚点跳转,但是也能解决显示不全的问题)
  • 2.绑定的事件写在setTimeout内,延迟执行;(能满足大部分需求)

演示代码:

DEMO

php杂记2

glob函数

// 获取所有php和txt文件,必须指定第二个参数为GLOB_BRACE才能使用{}
$files = glob('*.{php,txt}', GLOB_BRACE);

// 按照文件的修改时间排序
usort($files, create_function('$a,$b', 'return filemtime($a) - filemtime($b);'));

RecursiveDirectoryIterator

// 深度遍历文件夹
$path = realpath('/etc');

$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
    echo $name . PHP_EOL;
}

PHP5.3下SQLSTATE[HY000] [2002] 非法的参数解决方案

将localhost改成127.0.0.1

来自:链接