技术应用 – 青春部落,流年似水 http://www.youthtribe.com 青春是一场远行,总记不起来时的路。 Fri, 24 Mar 2023 10:13:36 +0000 zh-CN hourly 1 https://wordpress.org/?v=6.1.6 技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/2023 Fri, 24 Mar 2023 09:09:17 +0000 http://www.youthtribe.com/?p=2023 自己设计的苹果ios的一个类似安卓的TOAST的信息显示提示功能,基于swift5开发。可以指定 显示时长。单位 秒,可以是小数,比如2.5秒。

//
//  Tools.swift
//  Mark
//
//  Created by nelson on 2022/12/14.
//

import Foundation
import UIKit
// 自己整的一个工具类
class Tools {
    static func toast(msg:String,seconds:Double,vc:UIViewController){
        
        //得到当前 UIViewController 的 安全显示区域
        
        let insets:UIEdgeInsets = vc.view.safeAreaInsets
        //开始测量当前内容要显示的 大小,宽度 不超过 最大宽度
        
        
        //不要紧贴着底部,留一个marging->to->bottom
        let marginBottom:CGFloat = 50
        
        let width = UIScreen.getScreenWidth() - insets.left - insets.right
        let height = UIScreen.getScreenHeight() - insets.top - insets.bottom - marginBottom
        
        let font:UIFont = UIFont.preferredFont(forTextStyle: .body)
        
        let dict = [NSAttributedString.Key.font : font]
        let msgRectTemp = (msg as NSString).boundingRect(with: CGSize(width: width , height: height), options: [.usesFontLeading,.usesLineFragmentOrigin], attributes: dict as [NSAttributedString.Key : Any], context: nil)
        
        //因为有insets,所以需要人为扩大 rect
        let msgRect = CGRect(x: 0, y: 0, width: Int(ceil(msgRectTemp.width)) + Int(MyLabelToast.insetHor * 2), height: Int(ceil(msgRectTemp.height)) + Int(MyLabelToast.insetVer * 2))
        
        
        let y = Int(UIScreen.getScreenHeight() - insets.bottom - msgRect.height - marginBottom)
        
        let x = insets.left + (CGFloat(width) - msgRect.width ) / 2
        
        var label:UILabel?
        
        let frame = CGRect(x: Int(x), y: y, width: Int(ceil(msgRect.width))  , height: Int(msgRect.height))

        label = vc.view.window?.windowScene?.windows.last?.viewWithTag(999) as? UILabel
        if(label == nil){
            //新建立
            label = MyLabelToast(frame: frame)
            
            label!.layer.masksToBounds = true // 不加这句 圆角会无效
            label!.layer.cornerRadius = 5
            
            label!.backgroundColor = UIColor.black.withAlphaComponent(0.5)
            label!.textColor = UIColor.white
            label!.font = font
            
            //
            label!.tag = 999
        }
        else{
            //不用新建立
            //label!.frame = frame
        }
        
        //
        label!.text = msg
        vc.view.window?.windowScene?.windows.last?.addSubview(label!)
        
        //下边的方法不可以!在pad上 ,不是全屏的vc时,会显示不正常
        //vc.view.addSubview(label!)
        
        //定时器
        let timer = Timer.scheduledTimer(withTimeInterval: seconds, repeats: false) { Timer in
            if(label != nil){
                label!.removeFromSuperview()
            }            
        }
        
        return
    }
}
extension UIScreen{
    static func getScreenWidth()->CGFloat{
        return UIScreen.main.bounds.size.width
    }
    static func getScreenHeight()->CGFloat{
        return UIScreen.main.bounds.size.height
    }    
    static func getScreenSize()->CGSize{
        return UIScreen.main.bounds.size
    }
}

用来呈现文字的label

//
//  MyLabelToast.swift
//  Mark
//
//  Created by nelson on 2023/3/21.
//
/*
 主要就是为了增加 toast 中 label的 padding
 */
import UIKit

class MyLabelToast: UILabel {

    static let insetHor:CGFloat = 20
    static let insetVer:CGFloat = 10
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
        let insets = UIEdgeInsets(top: 10, left: 20, bottom: 10, right: 20)
        super.drawText(in: rect.inset(by: insets))
//        super.draw(rect)
        
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.numberOfLines = 0
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

用法如下:

Tools.toast(msg: "青春部落!GREAT!www.youthtribe.com!", seconds: 3, vc: self)

效果如下,类似android的toast:

]]>
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1960 Sun, 06 Feb 2022 07:47:57 +0000 http://www.youthtribe.com/?p=1960 直接上代码吧,qt得到文件md5的值应该还是比较常用到的一个功能。

QString ThreadDownload::getFileMd5(QString filename)
{
    QFile theFile(filename);
    if(!theFile.open(QIODevice::ReadOnly)){
        return "failed";
    }
    QByteArray ba = QCryptographicHash::hash(theFile.readAll(), QCryptographicHash::Md5);
    theFile.close();
    return QString(ba.toHex());

}
]]>
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1950 Sat, 05 Feb 2022 17:57:20 +0000 http://www.youthtribe.com/?p=1950 这两天在捣鼓测试阿里云的对象存储,阿里云称为 阿里云对象存储OSS(Object Storage Service)。

首先,相关sdk是放在 github的。so,需要科学上网。很是不方便。

再者就是遇到了提供的教程默认编译出来的lib是64位的。我的项目均是32位下开发的。如果设置为win32的,vs编译时会有如下的提示:

错误 LNK1112 模块计算机类型“x86”与目标计算机类型“x64”冲突 cpp-sdk F:\迅雷下载\aliyun-oss-cpp-sdk-1.9.0\build\sdk\Debug\OssClient.obj 1

解决办法是修改项目的属性中的 文档管理程序的-》所有选项-》附加选项,/machine:x64 改为 /machine:x86

但好像各个vs版本的这个属性的位置有所不一样,注意区别对待。

还有如下问题:

阿里云oss也集成了相关的第三方库,libcurl,ssleasy等,这和我当前项目的不兼容。生成的exe程序会有如下提示:

然后我就用他提供的dll直接替换了我的原先的。简单看是没问题,可以正常执行(但真不确保就没问题呀,内心还是比较担心的)。所以还是需要仔细测试。

还有就是,好像他的第三方库的dll只有release版本的,没有debug的,这样的话,我的程序 在debug模式下就不能正常运行了,只能在release模式下开发了。。。这,也是个问题呀。。。不知道怎么整。。。

最开始是打算捣鼓腾讯云对象存储的,感觉腾讯的第三方库 也不好弄。poco。就放弃了。

]]>
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1946 Sat, 29 Jan 2022 02:45:32 +0000 http://www.youthtribe.com/?p=1946 我用的笔记本可以用百度搜索,但是却死活打不开百度知道和百度贴吧。后来想起来,我之前 是解决过这个问题的。原因就是把自己电脑的网络的IP6协议给禁用了,还用传统的IP4就可以了。至于具体是什么问题导致的不懒得研究搜索了。反正用IP4协议也没什么影响。

]]>
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1932 Thu, 06 Jan 2022 08:15:50 +0000 http://www.youthtribe.com/?p=1932 一些小黑客会试图通过正常的但高频的【正常访问】去查看我们网站的一些隐藏的页面,比如管理员登录页面。还有一种比较常见的是去扫描一些 行业内的 现成的 木马文件,来攻击我们的网站。因为短时间内会有大量的看似正常的请求,会造成性能不高的服务器的报警,如内存或者cpu,甚至带宽 吃紧,影响正常服务。

下图为非法请求示例

可以利用redis的高性能优势去做一些文章。

原理就是用网站程序去判断用户的请求,如果判断出是恶意的,那么把该访问者记录下来存储到redis中去。如果该访问者再来请求,那么直接给他返回500。正常情况来讲,黑客的扫描工具得知500相应码后,应该会停止扫描吧。就算不停止,那么redis的高性能也可以抵挡这些非法扫描请求,从而达到保护服务器的目的。通常可以设置一个小时内禁止该ip的正常访问。时间可以自己设置。

如何判断恶意访问:比如我的是php程序,如果用户的请求中出现了 .asp或者.jsp,或者hack,hacker字样,那么就判断你小子不老实,就打入冷宫。至于加哪些判断字符可以根据自己的需求进行设置。

需要服务器安装redis,我这里是用的php做了一个示例,我的php文件名为【illegal_deny.php】,用户可以直接在站点入口包含此文件即可。

require __DIR__.'/../app/diy/illegal_deny.php';

下边是文件内容。请根据自己的实际情况进行修改。

<?php
//redis的配置
//define('REDIS_SERVER_IP', '121.40.24.38');
define('REDIS_SERVER_IP', '127.0.0.1');
define('REDIS_SERVER_PORT', 6379);
//auth就是密码
define('REDIS_SERVER_AUTH', 'yourpassword');

//禁止访问的时间,单位秒 3600 = 1小时
define('DENY_TIME', 3600);


function getRedis($db = 0){
    
    $redis = new \Redis();
    $res = $redis->connect(REDIS_SERVER_IP,REDIS_SERVER_PORT);
    $redis->auth(REDIS_SERVER_AUTH);
    $redis->select($db);
    return $redis;
}

//如果是访问一些非法网址,比如黑客,就进行一段时间的访问屏蔽 begin
//非法访问次数
$illegal_attempt_count_key = 'ILLEGAL_ATTEMPT_COUNT';

//是否已经被限制访问
$illegal_key = "ILLEGAL_IP_".$_SERVER['REMOTE_ADDR'];
//$illegal_key = "ILLEGAL_IP_".$_SERVER['HTTP_X_FORWARDED_FOR'];



$uri = $_SERVER['REQUEST_URI'];


$redis = getRedis();
//$redis->delete($illegal_key);
if($redis->exists($illegal_key)){
 
    header('HTTP/1.1 500 Internal Server Error');
    exit(0);
}

$limit_time = DENY_TIME;//禁止时间,单位秒
//判断是否要进行限制

//几个禁止访问的目录
if($uri == '/admin'){
    //
    $redis->setex($illegal_key,$limit_time,date("Y-m-d H:i:s",time()));
    $redis->incr($illegal_attempt_count_key);
    header('HTTP/1.1 500 Internal Server Error');
    exit(0);
}

//限制访问地址包含的一些关键词,只要匹配到就进行限制
$illegal_urls = ['hack','hacker','.asp','.jsp'];
foreach ($illegal_urls as $url){
    if(strpos($uri, $url)){
        //
        $redis->setex($illegal_key,$limit_time,date("Y-m-d H:i:s",time()));
        $redis->incr($illegal_attempt_count_key);
        
        header('HTTP/1.1 500 Internal Server Error');
        exit(0);
    }
}
//如果是访问一些非法网址,比如黑客,就进行一段时间的访问屏蔽 over

附:对我的1cpu2G内存的服务器加了这个【护盾】后,服务器就不会再报警了(之前是cpu 一旦过90%使用率就会发邮件,短信,好烦)。真香!谁用谁说好。

]]>
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1919 http://www.youthtribe.com/archives/1919#respond Fri, 19 Nov 2021 20:49:15 +0000 http://www.youthtribe.com/?p=1919 chrome自动更新到 版本 96.0.4664.45(正式版本) (64 位)以后打开一些网站特别卡。会越来越卡,然后关了chrome 再打开就好了。网络搜索了一下,需要关闭什么安全链接。

点击右上角 三个点,设置,隐私设置和安全性,安全,使用安全dns ,关闭就可以了。chrome自己更新后,这个功能默认是打开的。也不知道这都是啥设置。。唉,难受了我好几天。

http://www.nbqq.net/article/show/68

]]>
http://www.youthtribe.com/archives/1919/feed 0
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1915 http://www.youthtribe.com/archives/1915#respond Tue, 02 Nov 2021 09:07:41 +0000 http://www.youthtribe.com/?p=1915
&#8195;
android:text="&#8195;&#8195;号:"
]]>
http://www.youthtribe.com/archives/1915/feed 0
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1905 http://www.youthtribe.com/archives/1905#respond Thu, 23 Sep 2021 16:43:14 +0000 http://www.youthtribe.com/?p=1905 主要就是要设置一下邮件的编码方式。默认的是CHARSET_ISO88591,改为CHARSET_UTF8就可以了。按说UTF8应该是国际通用的主流吧,但不知道基于什么目的这个PHPMailer默认的不是utf8.

$mail = new PHPMailer(true);
$mail->CharSet = PHPMailer::CHARSET_UTF8;
//或者
//$mail->CharSet = 'utf-8';

版本为phpmailer: 6.1.7

]]>
http://www.youthtribe.com/archives/1905/feed 0
技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1869 http://www.youthtribe.com/archives/1869#respond Thu, 08 Apr 2021 09:52:20 +0000 http://www.youthtribe.com/?p=1869 上传文件

QNetworkAccessManager manager;
QUrl url;
/* 设置通讯协议 */
url.setScheme("ftp");    
/* 设置用户名 */  
url.setUserName("root");  
/* 设置密码 */ 
url.setPassword("123456"); 
/* 设置主机,也可以是域名 */
url.setHost("127.0.0.1");
/* 设置端口号,一般为21 */  
url.setPort(21);         
/* 设置路径 */ 
url.setPath("/tmp/hello.png"); 

/* 装载本地文件 */
QFile file("/Desktop/hello.png"); 
file.open(QIODevice::ReadOnly);
/* 读取本地文件数据 */
QByteArray data = file.readAll(); 
file.close();

QNetworkRequest request(url);
/* 上传数据,上传成功后会在远端创建/tmp/hello.png文件 */
QNetworkReply* reply = manager.put(request, data); 

QEventLoop eventLoop; 
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
/* 进入等待,但事件循环依然进行 */
eventLoop.exec(); 

if (reply->error() != QNetworkReply::NoError) {
    qDebug() << "Error: " << reply->errorString();
}

下载文件

QNetworkAccessManager manager;
QUrl url;
/* 设置通讯协议 */
url.setScheme("ftp");      
/* 设置用户名 */
url.setUserName("root");   
/* 设置密码 */
url.setPassword("123456"); 
/* 设置主机,也可以是域名 */
url.setHost("127.0.0.1");  
/* 设置端口号,一般为21 */
url.setPort(21);           
/* 设置路径 */
url.setPath("/tmp/test.txt"); 

QNetworkRequest request(url);
/* 执行Get请求 */
QNetworkReply* reply = manager.get(request); 

QEventLoop eventLoop;
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
/* 进入等待,但事件循环依然进行 */
eventLoop.exec(); 

if (reply->error() == QNetworkReply::NoError) {
    /* 创建本地文件 */
    QFile file("test.txt"); 
    file.open(QIODevice::WriteOnly);
    /* 写入文件 */
    file.write(reply->readAll()); 
    file.close();
}
else {
    qDebug() << "Error: " << reply->errorString();
}

总结

  • 上传文件:配置url->加载数据->put操作
  • 下载文件:配置url->get操作->获取数据保存到文件
  • 如服务端没有身份验证,客户端可以省略用户名和密码操作。
  • https://zhuanlan.zhihu.com/p/92496797

    ]]>
    http://www.youthtribe.com/archives/1869/feed 0
    技术应用 – 青春部落,流年似水 http://www.youthtribe.com/archives/1810 http://www.youthtribe.com/archives/1810#respond Sat, 19 Jan 2019 06:06:53 +0000 http://www.youthtribe.com/?p=1810 就是访问你的域名可以,但是http://localhost就不可以了

    解决办法,编辑配置文件httpd.conf,注释掉一行就可以了:

    #ServerName 192.168.1.3:80 

    servername后边内容可能不一样,但主要就是这一行,注释掉就可以了。

    ]]>
    http://www.youthtribe.com/archives/1810/feed 0