Snow Leopard Server 上配置 Gitosis 笔记

为了迁移项目 Git 仓库到 Mini Server 上,需要在 Snow Leopard Server 上配置一下 Gitosis,但是 Mac OS X 和 Linux 不太一样,有些地方需要特殊处理一下。

安装 Gitosis

Gitosis 的安装就不多说,在参考文档2中有。

添加 Git 用户组及用户

添加用户可以用参考文档1中的方法来创建,没有尝试直接用 OSX 的用户管理来创建是否可用。

# 这里的用户组和用户ID 用 401,但是实际用时需要根据服务器上的情况来创建
# 我在使用时 401 这个 gid 就已经被占用了,可以使用以下两个命令看看要用的
# ID 是否已经被用了。
sudo dscl . list /Users uid
sudo dscl . list groups gid
 
# 创建用户组 git
sudo dscl . create groups/git
sudo dscl . create groups/git gid 401
 
# 创建用户 git
sudo dscl . create users/git
sudo dscl . create users/git uid 401
sudo dscl . create users/git NFSHomeDirectory /Users/git
sudo dscl . create users/git gid 401
sudo dscl . create users/git UserShell /bin/bash
sudo dscl . create users/git Password '*'
 
# 创建用户主目录,Git 仓库就要放在里面
sudo mkdir /Users/git
sudo chown git /Users/git
sudo chgrp git /Users/git
 
# 下面这一句是把 git 用户添加到可以使用 ssh 访问的用户组里面
# 如果不执行这句的话,git push 或者 git pull 等等的时候会出错
sudo dscl . -append /Groups/com.apple.access_ssh GroupMembership git

配置 Gitosis

这个在参考文档2中都有详细说明。

参考文档

  1. git hosting with Leopard, Ian White
  2. 权限管理器 Gitosis, Pro Git
  3. Adduser for Mac OS X = dscl + niutil + nicl, otaku ramblings

[Cocoa学习]格式化日期和解析日期字符串

在应用程序中,显示消息的时候一般都需要附带一个消息接收的时间,使用 NSDate 和 NSDateFormatter 即可完成格式化输出日期的任务,但是在使用时会比较麻烦,通过 Category 的方式来给 NSDate 类直接添加两个类方法来做这些事情会比较好,在以后需要格式化字符串时不需要每次都去创建一个 NSDateFormatter 对象。

对于解析日期时间也是同理。

@interface NSDate (FormatString)
 
- (NSString*)stringWithFormat:(NSString*)fmt;
+ (NSDate*)dateFromString:(NSString*)str withFormat:(NSString*)fmt;
 
@end
 
@implementation NSDate (FormatString)
 
- (NSString*)stringWithFormat:(NSString*)fmt {
    static NSDateFormatter *fmtter;
 
    if (fmtter == nil) {
        fmtter = [[NSDateFormatter alloc] init];
    }
 
    if (fmt == nil || [fmt isEqualToString:@""]) {
        fmt = @"HH:mm:ss";
    }
 
    [fmtter setDateFormat:fmt];
 
    return [fmtter stringFromDate:self];
}
 
+ (NSDate*)dateFromString:(NSString*)str withFormat:(NSString*)fmt {
    static NSDateFormatter *fmtter;
 
    if (fmtter == nil) {
        fmtter = [[NSDateFormatter alloc] init];
    }
 
    if (fmt == nil || [fmt isEqualToString:@""]) {
        fmt = @"HH:mm:ss";
    }
 
    [fmtter setDateFormat:fmt];
 
    return [fmtter dateFromString:str];
}
 
@end

在这里,dataFromString 和 stringWithFormat 如果没有指定格式字符串参数的话,默认会使用 HH:mm:ss 来格式日期,当然,如果实际应用场景不一样,这里也可以修改。

如果需要更强大的功能,也可以去修改两个方法来符合自己的需要。

// 获取当前时间的字符串
NSString *now = [[NSDate date] stringWithFormat:@"HH:mm:ss"];
 
// 将一个字符串解析成 NSDate 对象
NSStirng *recvTime = @"2010-05-25 16:58:34 +0800";
NSDate  *recv = [NSDate dateFromString:recvTime withFormat:@"yyyy-MM-dd HH:mm:ss Z"];

使用 Category 给 NSDate 类添加这两个方法后,再要格式化日期或者解析日期时间字符串,就不需要额外去创建 NSDateFormatter 对象了,可以省不少力气。

参考资料

[Cocoa学习] 限制 NSTextField 中输入文本的长度

需求

NSTextField 作为一个常用的输入控件,有些在使用时需要去限制其中可以输入文本的长度,而 NSTextField 本身并没有提供这个功能,这就需要我们自己去想办法来实现了。

方法

在网上找了一下,发现可以通过继承 NSFormatter 实现一个子类来实现这个功能,参考了一下找到的代码[1],再将主要的 isPartialStringValid 方法根据自己的需要改了一下。

 
- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
       proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
              originalString:(NSString *)origString
       originalSelectedRange:(NSRange)origSelRange
            errorDescription:(NSString **)error 
{
    int size = [*partialStringPtr length];
    if ( size > maxLength ) {
        if (origSelRange.location == [origString length]) {
            // 如果修改的位置在原来字符串的最后,则不做修改,只是拒绝内容修改
        } else {
            // 如果修改的位置在原来字符串的中间,就根据剩余的可用的长度把新增加的字符串进行截取
            int preLen = origSelRange.location + (maxLength - [origString length]) + origSelRange.length;
            *partialStringPtr = [NSString stringWithFormat:@"%@%@",
                                 [*partialStringPtr substringToIndex:preLen],
                                 [origString substringFromIndex:origSelRange.location+origSelRange.length]];
 
            (*proposedSelRangePtr).location = preLen;
        }
 
        return NO;
    }
    return YES;
}

参考资料

iWangWang v0.3.0 Released

在上一个版本发布之后,过了两个月的时间,终于又有一个可以发布的版本了。

使用菜单中的“检查更新”既可完成更新,或者前往 Google Code 下载。

这次的更新如下:

  • [FIX] 修正在 Snow Leopard 中无法在 Dock 上显示未读消息数目的bug
  • [FIX] 修正在网页中点击旺旺图标无法打开聊天窗口的bug
  • [FIX] 修正无法使用“指定发送”和“添加好友”功能的bug
  • [FIX] 修正表情选择框在一些情况下引起程序崩溃的bug
  • [FIX] 修正在聊天窗口中无法指定发送功能无法使用的bug
  • [FIX] 修正一些菜单无法在所有窗口中使用的bug
  • [NEW] 现在可以使用 Ctrl+N 同时运行多个 iWangWang 来实现同时登录多个淘宝帐号
  • [NEW] 现在如果聊天时消息发送失败,可以重新输入验证码
  • [NEW] 登录后会恢复上一次退出时主窗口的位置
  • [NEW] 表情选择框现在可以用 ESC 键关闭
  • [NOTE] 有bug可以在 http://code.google.com/p/iwangwang/issues/entry 提出

这次主要修正了 iWangWang 在 Snow Leopard 下的兼容性,之前的开发环境是 Leopard,没能在 Snow Leopard 中好好测试。

如果有问题请邮件至 ohdarling88 at gmail dot com,或在 http://code.google.com/p/iwangwang/issues/entry 填写问题表单。

Enjoy it.

Xu Jiwei

iWangWang for Mac v0.2.0 发布

iWangWang v0.2.0 更新日志

  • [NEW] 在 Dock 上显示未读消息的个数
  • [NEW] 在“窗口”菜单中显示已经打开聊天窗口的列表
  • [FIX] 修正即使没有勾选“记住密码”时复选框还是会被自动选中的bug
  • [FIX] 修正登录超时导致程序崩溃的bug
  • [FIX] 修正“指定发送”中发送给自己时,关闭消息框后无法继续输入用户名的bug
  • [FIX] 修正在升级时关闭窗口会导致程序崩溃的bug
  • [FIX] 更新旺旺图标聊天脚本,修正了在某些页面点击图标聊天会出现乱码的bug,请重新安装用户脚本即可,用户脚本地址请参考
  • http://www.xujiwei.com/blog/iwangwang/use-iwangwang-in-browsers/
  • [MOD] 使用邮件来代替 Google Docs 进行使用反馈
  • [MOD] 调整了一下分组按钮的背景

安装

可以使用菜单“iWangWang》检查更新”来自动安装或访问下面这个地址来下载安装:
http://iwangwang.googlecode.com/files/iWangWang-v0.2.0.zip

旺旺图标点击聊天脚本更新

这次更新的还有浏览器中旺旺图标点击聊天的脚本,修正了在淘宝宝贝详情页点击卖家旺旺图标出现乱码导致而无法聊天的bug
安装指南:
http://www.xujiwei.com/blog/iwangwang/use-iwangwang-in-browsers/

已经安装的用户可以只需要重新安装用户脚本,用户脚本地址:
http://iwangwang.googlecode.com/hg/wwprotocol.user.js

反馈

如果您有任何建议或意见,请发送邮件到 ohdarling88 # gmail dot com,谢谢:)

[HOWTO] 在 Mac 下的 Safari 中直接打开 iWangWang 进行聊天

鉴于支付宝已经发布供 Safari 使用的安全登录控件,并且 Safari 可以自动调用关联程序来打开自定义协议,所有 Safari 下的点击旺旺图标打开 iWangWang 进行聊天比较容易实现,使用一个用户脚本就行。

要实现在 Safari 中点击旺旺图标进行聊天,步骤如下:

  1. 安装 SIMBL
    下载地址:http://www.culater.net/software/SIMBL/SIMBL.php
    SIMBL 可以理解为一个扩展加载器,因为 Safari 本身并不支持扩展机制,所有 SIMBL 使用了一种 Hack 的方式来方便加载第三方扩展。
  2. 安装 GreaseKit
    下载地址:http://8-p.info/greasekit/
    GreaseKit 是一个类似于 GreaseMonkey 的扩展,可以通过它在 Safari 运行用户脚本。
    如果你的系统是 Mac OS X Leopard,那么可能会出现安装 GreaseKit 失败的情况,这时可以试试一位网友重新编译的 GreaseKit,下载地址,关于这个问题的讨论可以看这里
  3. 最后,安装 iWangWang 聊天用户脚本
    安装地址:http://iwangwang.googlecode.com/hg/wwprotocol.user.js
    如果已经正确安装了 GreaseKit,那么在访问这个地址时,浏览器会询问是否安装“WangWang Protocol Handler”,选择“是”即可。

如果你已经将 iWangWang 放到了应用程序目录,那么在点击旺旺图标聊天时,会自动打开 iWangWang,如果 iWangWang 没有放到应用程序目录,那么你可能需要先运行 iWangWang 才可以使用点击旺旺图标进行聊天的功能。

如果有任何问题请联系我 ohdarling88 # gmail dot com

iWangWang v0.1.2 for Mac 发布

iWangWang 是一个在 Mac OS X 下使用的 Web 旺旺的客户端,使用 Mac 用户在淘宝购物时也可以方便地与卖家沟通,不需要每次打开 Web 旺旺,以及弥补 Web 旺旺不支持联系人列表及聊天记录的缺陷,并且目前只支持淘宝网帐号登录。

iWangWang 使用 REALbasic 编写,因为是基于 Web 旺旺的,所以 Web 旺旺不支持的功能 iWangWang 也没有实现,包括但不限于旺旺群、自定义表情、文件传送,并且和某一个联系人第一次聊天时,需要输入验证码。

注意:

  1. 这纯粹是我个人出于兴趣而制作的一个程序,与公司无关。
  2. 因为使用非公开接口,协议通过黑盒分析所得,因此有可能会由于 Web 旺旺修改通信协议而导致程序无法使用。
  3. 由于缺乏艺术细胞,因此程序界面仿照 MacQQ,如果觉得有内容侵犯了您的权利,请及时联系我修改,谢谢 :)
  4. 因为淘宝帐号涉及到金钱,所以如果不放心请不要使用这个程序 :)

如果有任何问题或建议,请联系 ohdarling88 # gmail dot com,或者点击菜单“文件》填写使用反馈”来填写反馈内容。

14:40 Update 更新下载链接,修正了接收带有自定义表情的消息时会导致程序崩溃的bug,如果已经下载,可以直接点击菜单“iWangWang > 检查更新”

下载地址:http://iwangwang.googlecode.com/files/iWangWang-v0.1.2.zip

HostsManager v0.4.1

使用 REALbasic 写的一个 hosts 文件管理工具,可以快速方便的管理系统中的 hosts,支持 Mac OS X 与 Windows。

注:Vista 和 Win7 需要使用管理员权限运行。

如果有bug或建议,请发送邮件到 ohdarling88 # gmail dot com

下载:

在 REALbasic 中注册 AppleEvent

之前为了注册一个自定义协议,需要通过注册 AppleEvent 来实现,在 Objective-C 中,可以很方便的使用 NSAppleEventManager 来注册 AppleEvent 句柄,但是在 REALbaisc 中,是没有办法直接去调用 NSAppleEventManager 的,所以需要通过声明然后调用 C API 来实现相应的功能。

与 NSAppleEventManager 中功能相对应的 C API 有 AEInstallEventHandler, NewAEEventHandlerUPP 等,通过这些 API 我们也可以在 REALbasic 中来注册 AppleEvent 了,再配合 Info.plist 中的 URLScheme 声明,即可实现 URL 自定义协议处理句柄。

#if TargetCarbon
    soft declare function AEInstallEventHandler Lib CarbonLib ( _
    theAEEventClass as Integer, _
    theAEEventID as Integer, _
    handler as Integer, _
    handlerRefcon as Integer, _
    isSysHandler as Boolean) as Integer
 
    Soft Declare Function NewAEEventHandlerUPP Lib CarbonLib (userRoutine as Ptr) as Integer
 
    Static CallbackUPP as Integer = 0
    If CallbackUPP = 0 then
      dim m as MemoryBlock =  AddressOf ForwardCarbonAEEventToObject
      If m is nil then
        Return
      End if
      CallbackUPP = NewAEEventHandlerUPP(m)
    End if
 
    dim v as Variant = me
 
    dim OSError as Integer = AEInstallEventHandler( _
    OSTypeToUInt(kInternetEventClass), _
    OSTypeToUInt(kAEGetURL), _
    CallbackUPP, _
    v.Hash, false)
 
    msgbox str(OSError)
#endif

先使用 NewAEEventHandlerUPP 来生成一个 AppleEvent 回调函数的句柄,然后调用 AEInstallEventHandler 来注册一个共享函数 ForwardCarbonAEEventToObject 为 AppleEvent 事件处理句柄。

AEInstallEventHandler 所需的 AEEventClass 和 AEEventID 都是一个 4 字节的整型,但是通常我们在调用的时候,是用的一个 4 字符的字符串,因此需要一个函数来将 4 字符转换为 4 字节的整形。

// code from ToolbarSearchField by The ZAZ Studios
// http://www.thezaz.com/opensource/realbasic/macosx/searchfield/
static m as new MemoryBlock(4)
m.LittleEndian = false
m.StringValue(0, 4) = s
return m.UInt32Value(0)

在 ForwardCartonAEEventToObject 里,参数 theEvent 和 replyEvent 都量个整形,为了从这两个参数里拿到数据,还需要使用 AEGetParamPtr 来从 AppleEvent 中拿到数据。

soft declare function AEGetParamPtr lib CarbonLib ( _
    theAppleEvent as Integer, theAEKeyword as Integer, _
    desiredType as Integer, byref actualType as Integer, _
    dataPtr as Ptr, maximumSize as Integer, _
    byref actualSize as Integer) as Integer

当然还有一系列的 AEGetDataDesc、AEGetDescSize 等函数可以,具体可以查 Xocde 随带的库文档。

关于注册自定义协议,可以参考这篇文章

通过 Core Foundation 中的一些 C API,在 REALbasic 也可以完成一些平台相关的工作,虽然麻烦了些:)

博客迁移到 Wordpress 平台

花了两天人肉把老博客的大部分技术文章迁移到 Wordpress,评论数据不迁了,工作难度太大……

如果您是从外部链接进来的,例如 www.xujiwei.com/blog/?id=123 这样的形式,那就会找不到页面,可以使用右上角的搜索来搜索相关的文章。

以后会陆续把剩下的文章迁移过来:)