阿里云ECS服务器配置ubuntu安装openfire服务器

Posted by Jimney Lee at 2014-10-31 with tags openfire, xmpp

最近搞了一台阿里云的ECS服务器,因为搞活动半年免费,所以就申请了一台,过两天就批准下来,顺便多花了1百多RMB买了固定IP。总体说来还是挺值的,觉得一个人用挺浪费,分享出来跟大家一起玩玩。

搞台服务器主要为了学习即时聊天功能模块的开发,服务器采用OpenFire,i OS前端基于XMPPFrameWork,经过一段时间学习,写了一个开源作品JLWeChat,已从oschina的私有仓库转移到github,欢迎参与讨论交流。

主要功能类似微信的简单聊天功能,包括表情、图片、音频,后台存储基于七牛免费提供云存储。

下面记录下在阿里云ECS服务器配置OpenFire的过程,需要的同学可以参考下,少走弯路。

下载OpenFire安装文件

1、安装Axel

Axel是一个命令行下载工具

$ apt-get install axel

2、下载OpenFire安装文件,目前最新为3.9.3

$ wget -O openfire.tar.gz http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3_9_3.tar.gz

3、解压到/opt > If using the .tar.gz, extract the archive to /opt or /usr/bin:

$ tar -xzvf openfire_3_9_3.tar.gz
$ mv openfire /opt

安装mysql

1、执行安装命令

$ netstat -tap | grep mysql

如果遇到下面这个错误,请执行下面操作 > apt-get install mysql-server : Depends: mysql-server-5.5 but it is not going to be installed

$ apt-get autoremove mysql* --purge
$ apt-get remove apparmor
$ apt-get install mysql-server mysql-common

创建OpenFire需要的数据库

$ mysql -u

mysql> create database openfire;
mysql> use openfire
mysql> source /opt/openfire/resources/database/
openfire_mysql.sql;

启动OpenFire服务器

$ /opt/openfire/bin/openfire start

网页配置OpenFire

1、数据库设置如下

jdbc:mysql://121.41.129.248:3306/openfire?useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8

ios http请求出现502-bad-gateway错误

Posted by Jimney Lee at 2014-01-11 with tags iphone, nginx

当我试着在Ruby China社区的iPhone客户端基础上,兼容v2ex社区Project Babel api接口。 请求遇到502-bad-gateway错误,一开始以为是使用AFNetworking的问题,我通过NSString同步获取,发现也没获取到,所以我推测应该是跟后台基于nginx反向代理有关。

header输出结果比较:

1、使用AFNetworking框架底层设置的User-Agent默认值 整个请求头如下:

{
    Accept = "application/json";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    "User-Agent" = "JLV2EX/1.0 (iPhone Simulator; iOS 7.0.3; Scale/2.00)";
}

请求报错:502 bad gateway :(

2、通过手机浏览器打开http://whatsmyuseragent.com/来获取到User-Agent,再赋给header的User-Agent 整个请求头,

{
    Accept = "application/json";
    "Accept-Language" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5";
    "User-Agent" = "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B508 Safari/9537.53";
}

可以顺利获取信息 :)

网上google了一通,找到如下解决方案。特此记录。参考SO帖子: http://stackoverflow.com/questions/8487581/uiwebview-ios5-changing-user-agent/8666438#8666438

//RCAPIClient继承于AFHTTPClient,做如下修改:
- (id)initWithBaseURL:(NSURL *)url
{
    self = [super initWithBaseURL:url];
    if (self) {
        self.parameterEncoding = AFJSONParameterEncoding;
        
        // 502-bad-gateway error, set user agent from http://whatsmyuseragent.com/
        // http://stackoverflow.com/questions/8487581/uiwebview-ios5-changing-user-agent/8666438#8666438
        if (ForumBaseAPIType_V2EX == FORUM_BASE_API_TYPE) {
            NSString* testUserAgent = @"Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_3 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11B508 Safari/9537.53";
            [self setDefaultHeader:@"User-Agent" value:testUserAgent];
        }
    }
    return self;
}

代码见:https://github.com/jimneylee/JLRubyChina-iPhone/blob/master/JLRubyChina/Common/RCAPIClient.m的initWithBaseURL方法

自定义xopen命令打开工程

Posted by Jimney Lee at 2014-01-09 with tags xcode, ruby

通常我们在使用CocoaPods命令’[sudo] pod update’安装好依赖库,会自动生成projectname.xcworkspace,通过打开workspace来正确打开所有工程。在终端使用系统的open命令打开,我们要细心注意后缀projectname.xcodeproj,还是projectname.xcworkspace,这样很麻烦。 通过下面这个简单的ruby脚本,只需要xopen projectname就可以优先打开projectname.xcworkspace

#!/usr/bin/env ruby
 
require 'shellwords'
 
proj = Dir['*.xcworkspace'].first
proj = Dir['*.xcodeproj'].first unless proj
 
if proj
  puts "Opening #{proj}"
  `open #{proj}`
else
  puts "No xcworkspace|xcproj file found"
end

把这个文件拷贝到/usr/local/bin目录下,并添加权限:chmod 777 xopen

参考:http://www.marcelofabri.com/xopen/

实现微博图片查看原图功能

Posted by Jimney Lee at 2014-01-07 with tags iphone, weibo

今天在我的开源新浪微博客户端上加上这个功能。之前预想实现比较复杂,今天详细考虑下,实现还是比较简单,核心代码是10来行即可搞定。

实现思路剖析

1、获取视图动画的初始frame

这个功能实现的复杂性在于,微博Cell本身视图内容就多层嵌套,包含当前微博和被转发微博,同时Cell又是位于tableView上,视图显示的UI比一般的简单布局要复杂多。 但是我们通过将图片视图,从当前父视图,往上层父视图转换,一直到window级别,这样我们就准确获取到动画放大显示前的原位置,对应于fromRect。

- (void)showContentOriginImage
{
    if (self.viewController) {
        if ([self.viewController isKindOfClass:[UITableViewController class]]) {
            UITableView* tableView = ((UITableViewController*)self.viewController).tableView;
            UIWindow* window = [UIApplication sharedApplication].keyWindow;
            
            // convert rect to self(cell)
            CGRect rectInCell = [self.contentView convertRect:self.contentImageView.frame toView:self];
    
            // convert rect to tableview
            CGRect rectInTableView = [self convertRect:rectInCell toView:tableView];//self.superview
            
            // convert rect to window
            CGRect rectInWindow = [tableView convertRect:rectInTableView toView:window];
            
            // show photo full screen
            UIImage* image = self.contentImageView.image;
            if (image) {
                rectInWindow = CGRectMake(rectInWindow.origin.x + (rectInWindow.size.width - image.size.width) / 2.f,
                                          rectInWindow.origin.y + (rectInWindow.size.height - image.size.height) / 2.f,
                                          image.size.width, image.size.height);
            }
            SMFullScreenPhotoBrowseView* browseView =
            [[SMFullScreenPhotoBrowseView alloc] initWithUrlPath:self.statusEntity.original_pic
                                                       thumbnail:self.contentImageView.image
                                                        fromRect:rectInWindow];
            [window addSubview:browseView];
        }
    }
}

2、原图下载进度显示

通过实现MBRoundProgressViewMBRoundProgressViewDelegate方法,计算当前图片的下载进度progress,进度视图采用MBRoundProgressView,实现比较容易

- (void)networkImageView:(NINetworkImageView *)imageView readBytes:(long long)readBytes totalBytes:(long long)totalBytes
{
    CGFloat progress = (float)readBytes / (float)totalBytes;
    self.progressIndicator.progress = progress;
}

3、图片缩放功能

难点在于缩放的同时,调整imageView的center始终位于中间位置,主要考虑imageView高度小于屏幕高度后center调整,这边实现我参考SO的解答:http://stackoverflow.com/questions/1316451/center-content-of-uiscrollview-when-smaller 以前这个问题困扰我很久,今天终于得到解决,挺高兴的。

-(void)scrollViewDidZoom:(UIScrollView *)scrollView {
    CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?
    (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5f : 0.f;
    
    CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?
    (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5f : 0.f;
    
    self.imageView.center = CGPointMake(scrollView.contentSize.width * 0.5f + offsetX,
                                 scrollView.contentSize.height * 0.5f + offsetY);
}

4、图片保存

保存功能实现比较简单,偷懒情况下一句UIImageWriteToSavedPhotosAlbum即可搞定,但是对于稳定性比较高的APP还是需要严格的书写和良好的提示

- (void)savePhoto
{
	if (self.isOriginPhotoLoaded && self.imageView.image) {
        __block MBProgressHUD* hud = [MBProgressHUD showHUDAddedTo:self animated:YES];
        hud.labelText = @"保存中...";
        self.saveBtn.enabled = NO;
        UIImageWriteToSavedPhotosAlbum(self.imageView.image, self,
                                       @selector(image:didFinishSavingWithError:contextInfo:), nil);
	}
    else {
        [SMGlobalConfig showHUDMessage:@"图片未下载完成,无法保存" addedToView:self];
    }
}

//pragma mark - SavedPhotosAlbum CallBack
-(void) image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    if (error) {
        [SMGlobalConfig showHUDMessage:@"保存失败" addedToView:self];
    }
    else {
        [MBProgressHUD hideHUDForView:self animated:YES];
        
        __block MBProgressHUD* hud = [MBProgressHUD showHUDAddedTo:self animated:YES];
        hud.customView = [[UIImageView alloc] initWithImage:[UIImage nimbusImageNamed:@"37x-Checkmark.png"]];
        hud.mode = MBProgressHUDModeCustomView;
        hud.labelText = @"保存成功";
        [hud hide:YES afterDelay:1.5f];
        
        self.saveBtn.enabled = YES;
    }
}

今天把之前一直困扰我的功能实现,现在感觉心情大好,希望给路过没有错过的同学一点帮助和提示,如果有什么问题,欢迎在github项目的issue,提出你的见解和想法。

回首2013,展望2014

Posted by Jimney Lee at 2014-01-05 with tags

回首2013年蛇年

做了哪些

  • 1、参与一个朋友公司的项目,做一个地方广电的智慧社区APP,暂未上线

  • 2、在新的公司开发了两个景区旅游的APP

  • 3、维护升级客户的一个美食类产品—瑞安美食大搜罗

  • 4、为一位英国华人朋友,开发了一款类似58分类信息发布的APP,目前已打算产品化,这款APP最近会上架,稍后补上下载链接

  • 5、写了一个简易微博的iPhone客户端,由于接口有限,目前比较简陋,已开源到github,传送门,后期会申请接口,陆续完善,欢迎路过同学fork&pull request

  • 6、为国内优秀社区Ruby China社区写了一个iPhone客户端,已开源到github,传送门,用于技术交流和新技术学习平台,欢迎路过同学fork&pull request。已提交到AppStore,过几天上架后,补充下载链接,欢迎使用和意见反馈

读了哪些

  • 1、王淮《打造Fackbook》
  • 2、吴军《浪潮之巅》
  • 3、Joe《软件随想录》
  • 4、松本行弘(まつもとゆきひろ) 《松本行弘的程序世界》
  • 4、卡耐基 《人性的弱点》
  • 5、罗杰斯《旅行,人生最有价值的投资》

学了什么


###展望2014马年

打算做哪些

  • 1、新做或参与一个伟大产品或有大量用户使用的APP产品
  • 2、深入学习Rails、深入学习Android,通过学习比较不同前端平台的异同点,提升技术高度。
  • 3、开源分享自己积累的小框架,主要是iOS平台
  • 4、持续有规律的健身,逝去的一年身体损了很多

打算读什么

  • 1、读一些经济类、历史武侠类书籍,且是纸质非电子书,拓宽自己的知识面和思考角度

  • 2、坚持学习英语和日语,并尝试工作中用上,否则学习效率太低下

git如何同步到多个git server

Posted by Jimney Lee at 2013-12-20 with tags git, github, gitcafe

打算把我在github开源的RubyChinaiPhone客户端,同时发布到osc(开源中国)和gitcafe。想更多的同学参与进来,交流和学习,同时我认为这也是一件有兴趣和意义的事。对自己的技术分享也有很大的帮助。

初步有这个想法(需求),开始尝试有没有这个可能,如何简单方便,同步多个仓库。得意于git的分布式特点,本地仓库与服务器是平等的,包括所有commit logs。也就是说不管提交到哪个git server,对本地仓库而言,只是多了一份clone,所以往多个git server提交时,只要修改.git/config,即可很方便地进行同步更新。

但是如果每次要提交不同的server,都要手工修改这个config,还是比较麻烦,而且容易出错。所以我只要写几个sh脚本,每次执行以下自动修改就很方便了。

具体操作如下:

  • step1: 拷贝github账户的SSH公钥,到其他账户,保持一样
  • step2: 在.git目录下cp多个config文件,命名如下:
    • github: config_github
    • gitcafe: config_gitcafe
    • osc: config_osc
  • step3:在.git目录下toch多个sh执行文件(chmod a+x file)
    • github: use_github.sh
    • gitcafe: use_gitcafe.sh
    • osc: use_osc.sh

使sh文件均可被执行:chmod a+x use*.sh 如想同步到gitcafe上,只需要到.git目录下执行:

$ ./use_gitcafe.sh
$ git push origin master

OK! 在同步到gitcaft,我遇到这个问题:

fatal: The remote end hung up unexpectedly Everything up-to-date

有可能是你一次提交的文件太大,需设置postBuffer大小,我需要50MB,所以:

$ git config http.postBuffer 52428800

$ git config https.postBuffer 52428800

参见SO:http://stackoverflow.com/questions/12651749/git-push-fails-rpc-failed-result-22-http-code-411