标签: Windows

  • 更改 Windows VPS 上的 RDP 远程桌面端口 图文教程

    更改 Windows VPS 上的 RDP 远程桌面端口 图文教程

    一般Windows系统的VPS,您可能需要考虑将 RDP 端口更改为非标准端口。默认情况下,RDP 协议使用端口 3389,该端口通常会被暴力破解和/或扫描。更改 Windows Server 的 RDP 侦听端口是您可以采取的额外安全步骤。

    在本教程中,我们将介绍如何更改 Windows VPS 上的 RDP 端口。

    • 通过远程桌面连接客户端登录您的 Windows VPS。
    • 连接到 VPS 后,启动注册表编辑器。 (在搜索区域输入regedit)
    • 导航到以下注册表子项:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp
    • 查找端口号
    • 单击“编辑”>“修改” ,然后单击“小数” 
    • 键入您要将 RDP 端口更改为的新端口号,然后单击“确定” 
    • 关闭注册表编辑器
    • 在 Windows 防火墙设置中允许新端口号
    • 重新启动 Windows 服务器。

    服务器完成重新启动后,您会注意到服务器不再响应标准端口上的 RDP 连接,因此您现在需要在通过 RDP 连接时指定端口。例如,VPSIP:端口号

    您是否更改 Windows VPS 上的 RDP 端口?部署基于 Windows 的服务器时还采取哪些其他安全措施?在下面的评论部分留下您的反馈!

  • CloudCone2024新年元旦活动 便宜 年付 美国VPS 支持Windows系统

    CloudCone2024新年元旦活动 便宜 年付 美国VPS 支持Windows系统

    CloudCone,至今已经有差不多十年的海外服务商。这个服务商的特点提供美国洛杉矶MC数据中心云服务器、VPS和独立服务器等产品,产品线是在发展,但是机房不清楚为什么就一直保持一个。而且这个服务商的产品还支持随时删除小时计费模式的,这一点我们可以在类似LinodeVultr服务商。

    时至2024年,各大服务商都在盘点当前的活动。这不有朋友群里提到是否有 CloudCone 活动的,他们需要比较便宜的年付VPS主机,而且是可以灵活删除更换IP的。这里CloudCone还是适合的。

    我们一起看看当前 CloudCone 服务商的促销活动。

    元旦活动(VPS主机)

    核心内存硬盘流量年付购买
    2核1G55G2T$17.12链接
    2核2G100G3T$29.80链接
    2核3G160G4T$42.59链接
    4核4G220G5T$55.90链接

    云服务器

    核心内存硬盘流量月付购买
    1核0.5G10G2T$1.65链接
    1核1G20G3T$2.88链接
    2核2G40G4T$5.35链接
    3核4G80G6T$10.26链接
    4核8G160G8T$21链接

    旧活动

    核心内存硬盘流量月付购买
    1核1G30G1T$19.38链接
    1核1G20G3T$32.94链接
    2核2G60G2T$34.75链接
    2核2G40G6T$59.10链接

    对于CloudCone服务商,提供的洛杉矶MC机房,速度上并非CN2优化,适合海外业务需要灵活调整IP的,比如可以随时删除重新开通,以及价格还是比较便宜的。如果开通的IP不通,可以删除重新开通。

  • 了解和管理 Windows 10 和 Windows 11 上 WSL 中的 Zone.Identifier 文件

    如果你经常使用适用于 Linux 的 Windows 子系统 (WSL),并且遇到将源代码从 Windows 10 或 Windows 11 复制到 WSL 目录后命名的文件,则你并不孤单。这些神秘文件可能会让许多用户感到困惑和烦恼。在这篇博文中,我们将深入探讨 Zone.Identifier 文件是什么、它们出现的原因以及如何有效地管理它们。<file_name>:Zone.Identifier

    什么是 Zone.Identifier文件?

    Zone.Identifier 文件是一种特定于 Windows 的机制,用于存储有关文件的来源或“区域”的信息。这些文件是作为 Windows 安全功能的一部分创建的。当您从 Internet 下载文件或从不受信任的源复制文件时,Windows 可能会为文件分配一个 Zone.Identifier 以跟踪其安全区域。

    了解文件名中的冒号

    文件名中存在冒号(例如,)表示这是文件系统中的备用数据流。在此上下文中,它用于存储与文件相关的扩展属性。<file_name>:Zone.Identifier

    冒号属性和扩展属性之间的关系

    实际上,文件名中的冒号与文件的扩展属性相关联。Windows 使用备用数据流来存储有关文件的其他元数据。对于 Zone.Identifier 文件,此元数据包括安全区域信息。

    如何防止 Zone.Identifier 文件

    许多用户发现这些Zone.Identifier文件在Linux环境中很烦人和不必要。幸运的是,有一些方法可以防止它们的创建或在它们出现时删除它们。

    解决方案 :使用别名

    一个有效的解决方案是创建一个别名,允许您在复制之前快速删除这些文件。以下是您可以添加到文件等中的别名示例:.bashrc

    alias rzi="rm -rf **/*Zone.Identifier"

    在复制文件之前运行将删除源目录中的所有 Zone.Identifier 文件。rzi

    解决方案 :添加到 .gitignore

    如果使用 Git 进行版本控制,则可以通过将以下行添加到项目的 .gitignore 文件来阻止跟踪 Zone.Identifier 文件:

    **/*Zone.Identifier
    

    解决方案 :手动删除

    若要删除现有的 Zone.Identifier 文件,可以在 WSL 终端中运行以下命令:

    find . -name "*Zone.Identifier" -type f -delete

    此命令将搜索并删除当前目录及其子目录中的所有 Zone.Identifier 文件。

    结论

    在 Windows 10 或 Windows 11 上使用 WSL 时,Zone.Identifier 文件可能会令人沮丧。但是,通过了解它们的用途并使用提供的解决方案,您可以有效地管理和防止这些文件使您的项目和目录混乱。

  • DatabaseMart 美国独立服务器评测 带宽不限制流量

    DatabaseMart 美国独立服务器评测 带宽不限制流量

    DatabaseMart 海外服务器提供商有提供三个美国机房的独立服务器、虚拟主机和云服务器等产品。在前面对于他们的美国VPS主机进行过评测,线路上看不是CN2优化线路,适合有需要海外业务需要的。他们有Win和Linux主机,包括外汇服务器、GPU服务器等,这里手上有一台美国独立服务器进行评测。

    方案CPU内存硬盘带宽价格
    Express Bare Metal SATAE3- 122016GB240GB SSD + 5TB SATA100$45/m
    Express Bare Metal SSDE3- 122032GB120GB SSD + 960GB SSD100$45/m
    Basic Bare Metal SSDE5-267064GB120GB SSD + 960GB SSD100$65/m
    Basic Bare Metal SATAE5-267032GB4x3TB SATA RAID 10100$65/m
    Professional Bare Metal (Linux Only)E5 -2660128GB120GB SSD + 960GB SSD100$91/m
    Advanced Bare MetalE5-2697v2128GB240GB SSD +2TB SSD100$123/m

    美国机房列表:

    •  Dallas, Texas (South US)
    •  Denver, Colorado (Central US)
    •  Kansas City, Missouri (Central US)

    这里是他们独立服务器的方案,如果有需要可以参考100M带宽不限制流量。默认是有三个美国机房的,可以根据需要后台工单找客服根据指定机房,但是默认选择是随机的。

    欧美节点还是比较稳定的。

    他们线路并非主打CN2所以可以理解并非CN2。常规的202.97.

    这里我选择的是100M带宽方案。

    服务器可选Linux和Win系统。带宽不限流量

    支持支付宝、微信付款(需要联系客服获取支付账号)

    价格优势,按最低配VPS对比,约为Vultr的1/3 (2GB RAM, 2 Cores, 60GB SSD: $4.99/m)

    VPS的Windows license没有额外收费

  • smbclient命令 – 存取SMB/CIFS服务器的用户端程序

    SMB与CIFS为服务器通信协议,常用于Windows95/98/NT等系统。smbclient(samba client)可让Linux系统存取Windows系统所分享的资源。

    语法格式:smbclient [参数]

    常用参数

    -L显示服务器端所分享出来的所有资源
    -U指定用户名称
    -s指定smb.conf所在的目录
    -O设置用户端TCP连接槽的选项
    -N不用询问密码

    参考实例

    列出某个IP地址所提供的共享文件夹:

    [root@jiloc ~]# smbclient -L 198.168.0.1 -U username%password

    像ftp客户端一样使用smbclient :

    [root@jiloc ~]# smbclient //192.168.0.1/tmp  -U username%password 

    执行smbclient命令成功后,进入smbclient环境,出现提示符:smb:/>

    这里有许多命令和ftp命令相似,如cd 、lcd、get、megt、put、mput等。通过这些命令,我们可以访问远程主机的共享资源。

    直接一次性使用smbclient命令:

    [root@jiloc ~]# smbclient -c "ls"  //192.168.0.1/tmp  -U username%password 

    或者:

    [root@jiloc ~]# smbclient //192.168.0.1/tmp  -U username%password smb:/>ls 

    创建一个共享文件夹:

    [root@jiloc ~]# smbclient -c "mkdir share1" //192.168.0.1/tmp -U username%password 
  • 腾讯云 云服务器精选爆品 轻量服务器 2核2G4M/5M 1.2折年付¥72元/年

    腾讯云 云服务器精选爆品 轻量服务器 2核2G4M/5M 1.2折年付¥72元/年

    腾讯云QCloud 618超级爆品活动 2022 6.1 ~ 6.14活动之后,老季发现腾讯云又开启了云服务器精选爆品的活动。

    腾讯云云服务器精选爆品,购买链接直达: https://www.jiloc.com/go/qcloud-act

    购买即赠·专区,产品首单专享

    最长免费续费3个月,活动规则>>  

    • 本专区内商品都不支持退款
    • 购买15天内需至领赠页面领取福利
    • 同一账号,赠送福利限领取1次

    新人·专区,产品首单专享

    秒杀·专区

    新老·同享

    爆款热卖、音视频通信、云数据库、CDN&存储、AI应用、中间件&大数据频道等

    更多活动

    更有域名专场等其他活动。有需要的小伙伴可以看看。

  • 宝塔面板2022年 618特惠活动

    宝塔面板2022年 618特惠活动

    目前,我们的服务器采用的WEB环境较多的会用到宝塔面板,当然我们也知道专业版和企业版权限是比较大的,功能上也比较多。如果我们有需要用到专业版和企业版的,可以在618期间选择有折扣活动。如果我们准备长期用的建议可以选择永久授权。

    618特惠活动于本月15日正式开启,企业版899元/年(送2张商业SSL证书),专业版永久授权1988元起,最高立减4700元。

    宝塔2022年618特惠活动直达链接:https://www.jiloc.com/go/bt

    活动一:购买企业版,赠送SSL证书

    1台企业版宝塔面板(Linux/Windows)优惠价只要899元/年,还会赠送2张商业SSL证书,企业版包含专业版插件以及企业版插件;1台宝塔Linux专业版活动价449元/年,1台宝塔Windows专业版活动价649元/年,包含免费版所有功能、Web应用防火墙、网站监控报表等。

    活动二:永久版授权1988元起

    活动规则

    活动一规则

    1、*购买后可在面板上直接通过抵扣券续费订单。

    2、企业版已包含QQ或微信客服,能更好的保障您的服务,如需加群,请购买企业版,微信扫描右下角二维码咨询。

    3、企业版包含专业版插件以及企业版插件,不含第三方应用插件。

    4、活动产品不参与返现。

    5、活动产品,不支持退款。可开发票,微信扫描右下角二维码咨询。

    6、活动截止日期:2022年6月18日 23:59:59。

    活动二规则

    1、*购买后可在面板上直接通过抵扣券续费订单。

    2、Linux/windows专业版为永久授权套餐。

    3、活动产品不参与返现。

    4、活动产品,不支持退款。可开发票,微信扫描右下角二维码咨询。

    5、活动截止日期:2022年6月18日 23:59:59。

  • TCP/UDP常见端口参考

    著名端口

    端口号码 / 层名称注释
    1tcpmuxTCP 端口服务多路复用
    5rje远程作业入口
    7echoEcho 服务
    9discard用于连接测试的空服务
    11systat用于列举连接了的端口的系统状态
    13daytime给请求主机发送日期和时间
    17qotd给连接了的主机发送每日格言
    18msp消息发送协议
    19chargen字符生成服务;发送无止境的字符流
    20ftp-dataFTP 数据端口
    21ftp文件传输协议(FTP)端口;有时被文件服务协议(FSP)使用
    22ssh安全 Shell(SSH)服务
    23telnetTelnet 服务
    25smtp简单邮件传输协议(SMTP)
    37time时间协议
    39rlp资源定位协议
    42nameserver互联网名称服务
    43nicnameWHOIS 目录服务
    49tacacs用于基于 TCP/IP 验证和访问的终端访问控制器访问控制系统
    50re-mail-ck远程邮件检查协议
    53domain域名服务(如 BIND)
    63whois++WHOIS++,被扩展了的 WHOIS 服务
    67bootps引导协议(BOOTP)服务;还被动态主机配置协议(DHCP)服务使用
    68bootpcBootstrap(BOOTP)客户;还被动态主机配置协议(DHCP)客户使用
    69tftp小文件传输协议(TFTP)
    70gopherGopher 互联网文档搜寻和检索
    71netrjs-1远程作业服务
    72netrjs-2远程作业服务
    73netrjs-3远程作业服务
    73netrjs-4远程作业服务
    79finger用于用户联系信息的 Finger 服务
    80http用于万维网(WWW)服务的超文本传输协议(HTTP)
    88kerberosKerberos 网络验证系统
    95supdupTelnet 协议扩展
    101hostnameSRI-NIC 机器上的主机名服务
    102iso-tsapISO 开发环境(ISODE)网络应用
    105csnet-ns邮箱名称服务器;也被 CSO 名称服务器使用
    107rtelnet远程 Telnet
    109pop2邮局协议版本2
    110pop3邮局协议版本3
    111sunrpc用于远程命令执行的远程过程调用(RPC)协议,被网络文件系统(NFS)使用
    113auth验证和身份识别协议
    115sftp安全文件传输协议(SFTP)服务
    117uucp-pathUnix 到 Unix 复制协议(UUCP)路径服务
    119nntp用于 USENET 讨论系统的网络新闻传输协议(NNTP)
    123ntp网络时间协议(NTP)
    137netbios-ns在红帽企业 Linux 中被 Samba 使用的 NETBIOS 名称服务
    138netbios-dgm在红帽企业 Linux 中被 Samba 使用的 NETBIOS 数据报服务
    139netbios-ssn在红帽企业 Linux 中被 Samba 使用的NET BIOS 会话服务
    143imap互联网消息存取协议(IMAP)
    161snmp简单网络管理协议(SNMP)
    162snmptrapSNMP 的陷阱
    163cmip-man通用管理信息协议(CMIP)
    164cmip-agent通用管理信息协议(CMIP)
    174mailqMAILQ
    177xdmcpX 显示管理器控制协议
    178nextstepNeXTStep 窗口服务器
    179bgp边界网络协议
    191prosperoCliffod Neuman 的 Prospero 服务
    194irc互联网中继聊天(IRC)
    199smuxSNMP UNIX 多路复用
    201at-rtmpAppleTalk 选路
    202at-nbpAppleTalk 名称绑定
    204at-echoAppleTalk echo 服务
    206at-zisAppleTalk 区块信息
    209qmtp快速邮件传输协议(QMTP)
    210z39.50NISO Z39.50 数据库
    213ipx互联网络分组交换协议(IPX),被 Novell Netware 环境常用的数据报协议
    220imap3互联网消息存取协议版本3
    245linkLINK
    347fatservFatmen 服务器
    363rsvp_tunnelRSVP 隧道
    369rpc2portmapCoda 文件系统端口映射器
    370codaauth2Coda 文件系统验证服务
    372ulistprocUNIX Listserv
    389ldap轻型目录存取协议(LDAP)
    427svrloc服务位置协议(SLP)
    434mobileip-agent可移互联网协议(IP)代理
    435mobilip-mn可移互联网协议(IP)管理器
    443https安全超文本传输协议(HTTP)
    444snpp小型网络分页协议
    445microsoft-ds通过 TCP/IP 的服务器消息块(SMB)
    464kpasswdKerberos 口令和钥匙改换服务
    468photurisPhoturis 会话钥匙管理协议
    487saft简单不对称文件传输(SAFT)协议
    488gss-http用于 HTTP 的通用安全服务(GSS)
    496pim-rp-disc用于协议独立的多址传播(PIM)服务的会合点发现(RP-DISC)
    500isakmp互联网安全关联和钥匙管理协议(ISAKMP)
    535iiop互联网内部对象请求代理协议(IIOP)
    538gdomapGNUstep 分布式对象映射器(GDOMAP)
    546dhcpv6-client动态主机配置协议(DHCP)版本6客户
    547dhcpv6-server动态主机配置协议(DHCP)版本6服务
    554rtsp实时流播协议(RTSP)
    563nntps通过安全套接字层的网络新闻传输协议(NNTPS)
    565whoamiwhoami
    587submission邮件消息提交代理(MSA)
    610npmp-local网络外设管理协议(NPMP)本地 / 分布式排队系统(DQS)
    611npmp-gui网络外设管理协议(NPMP)GUI / 分布式排队系统(DQS)
    612hmmp-indHMMP 指示 / DQS
    631ipp互联网打印协议(IPP)
    636ldaps通过安全套接字层的轻型目录访问协议(LDAPS)
    674acap应用程序配置存取协议(ACAP)
    694ha-cluster用于带有高可用性的群集的心跳服务
    749kerberos-admKerberos 版本5(v5)的“kadmin”数据库管理
    750kerberos-ivKerberos 版本4(v4)服务
    765webster网络词典
    767phonebook网络电话簿
    873rsyncrsync 文件传输服务
    992telnets通过安全套接字层的 Telnet(TelnetS)
    993imaps通过安全套接字层的互联网消息存取协议(IMAPS)
    994ircs通过安全套接字层的互联网中继聊天(IRCS)
    995pop3s通过安全套接字层的邮局协议版本3(POPS3)

    UNIX 特有的端口

    以下端口是 UNIX 特有的,涉及了从电子邮件到验证不等的服务。在方括号内的名称(如 [service])是服务的守护进程名称或它的常用别名。

    端口号码 / 层名称注释
    512/tcpexec用于对远程执行的进程进行验证
    512/udpbiff [comsat]异步邮件客户(biff)和服务(comsat)
    513/tcplogin远程登录(rlogin)
    513/udpwho [whod]登录的用户列表
    514/tcpshell [cmd]不必登录的远程 shell(rshell)和远程复制(rcp)
    514/udpsyslogUNIX 系统日志服务
    515printer [spooler]打印机(lpr)假脱机
    517/udptalk远程对话服务和客户
    518/udpntalk网络交谈(ntalk),远程对话服务和客户
    519utime [unixtime]UNIX 时间协议(utime)
    520/tcpefs扩展文件名服务器(EFS)
    520/udprouter [route, routed]选路信息协议(RIP)
    521ripng用于互联网协议版本6(IPv6)的选路信息协议
    525timed [timeserver]时间守护进程(timed)
    526/tcptempo [newdate]Tempo
    530/tcpcourier [rpc]Courier 远程过程调用(RPC)协议
    531/tcpconference [chat]互联网中继聊天
    532netnewsNetnews
    533/udpnetwall用于紧急广播的 Netwall
    540/tcpuucp [uucpd]Unix 到 Unix 复制服务
    543/tcpkloginKerberos 版本5(v5)远程登录
    544/tcpkshellKerberos 版本5(v5)远程 shell
    548afpovertcp通过传输控制协议(TCP)的 Appletalk 文件编制协议(AFP)
    556remotefs [rfs_server, rfs]Brunhoff 的远程文件系统(RFS)

    注册的端口

    列举了由网络和软件社区向 IANA 提交的要在端口号码列表中正式注册的端口。

    端口号码 / 层名称注释
    1080socksSOCKS 网络应用程序代理服务
    1236bvcontrol [rmtcfg]Garcilis Packeten 远程配置服务器
    1300h323hostcallscH.323 电话会议主机电话安全
    1433ms-sql-sMicrosoft SQL 服务器
    1434ms-sql-mMicrosoft SQL 监视器
    1494icaCitrix ICA 客户
    1512winsMicrosoft Windows 互联网名称服务器
    1524ingreslockIngres 数据库管理系统(DBMS)锁定服务
    1525prospero-np无特权的 Prospero
    1645datametrics [old-radius]Datametrics / 从前的 radius 项目
    1646sa-msg-port [oldradacct]sa-msg-port / 从前的 radacct 项目
    1649kermitKermit 文件传输和管理服务
    1701l2tp [l2f]第2层隧道服务(LT2P) / 第2层转发(L2F)
    1718h323gatediscH.323 电讯守门装置发现机制
    1719h323gatestatH.323 电讯守门装置状态
    1720h323hostcallH.323 电讯主持电话设置
    1758tftp-mcast小文件 FTP 组播
    1759mtftp组播小文件 FTP(MTFTP)
    1789helloHello 路由器通信端口
    1812radiusRadius 拨号验证和记帐服务
    1813radius-acctRadius 记帐
    1911mtpStarlight 网络多媒体传输协议(MTP)
    1985hsrpCisco 热备用路由器协议
    1986licensedaemonCisco 许可管理守护进程
    1997gdp-portCisco 网关发现协议(GDP)
    2049nfs [nfsd]网络文件系统(NFS)
    2102zephyr-srvZephyr 通知传输和发送服务器
    2103zephyr-cltZephyr serv-hm 连接
    2104zephyr-hmZephyr 主机管理器
    2401cvspserver并行版本系统(CVS)客户 / 服务器操作
    2430/tcpvenus用于 Coda 文件系统(codacon 端口)的 Venus 缓存管理器
    2430/udpvenus用于 Coda 文件系统(callback/wbc interface 界面)的 Venus 缓存管理器
    2431/tcpvenus-seVenus 传输控制协议(TCP)的副作用
    2431/udpvenus-seVenus 用户数据报协议(UDP)的副作用
    2432/udpcodasrvCoda 文件系统服务器端口
    2433/tcpcodasrv-seCoda 文件系统 TCP 副作用
    2433/udpcodasrv-seCoda 文件系统 UDP SFTP 副作用
    2600hpstgmgr [zebrasrv]HPSTGMGR;Zebra 选路
    2601discp-client [zebra]discp 客户;Zebra 集成的 shell
    2602discp-server [ripd]discp 服务器;选路信息协议守护进程(ripd)
    2603servicemeter [ripngd]服务计量;用于 IPv6 的 RIP 守护进程
    2604nsc-ccs [ospfd]NSC CCS;开放式短路径优先守护进程(ospfd)
    2605nsc-posaNSC POSA;边界网络协议守护进程(bgpd)
    2606netmon [ospf6d]Dell Netmon;用于 IPv6 的 OSPF 守护进程(ospf6d)
    2809corbaloc公共对象请求代理体系(CORBA)命名服务定位器
    3130icpv2互联网缓存协议版本2(v2);被 Squid 代理缓存服务器使用
    3306mysqlMySQL 数据库服务
    3346trnsprntproxyTrnsprnt 代理
    4011pxe执行前环境(PXE)服务
    4321rwhois远程 Whois(rwhois)服务
    4444krb524Kerberos 版本5(v5)到版本4(v4)门票转换器
    5002rfe无射频以太网(RFE)音频广播系统
    5308cfengine配置引擎(Cfengine)
    5999cvsup [CVSup]CVSup 文件传输和更新工具
    6000x11 [X]X 窗口系统服务
    7000afs3-fileserverAndrew 文件系统(AFS)文件服务器
    7001afs3-callback用于给缓存管理器回电的 AFS 端口
    7002afs3-prserverAFS 用户和组群数据库
    7003afs3-vlserverAFS 文件卷位置数据库
    7004afs3-kaserverAFS Kerberos 验证服务
    7005afs3-volserAFS 文件卷管理服务器
    7006afs3-errorsAFS 错误解释服务
    7007afs3-bosAFS 基本监查进程
    7008afs3-updateAFS 服务器到服务器更新器
    7009afs3-rmtsysAFS 远程缓存管理器服务
    9876sd会话指引器
    10080amanda高级 Maryland 自动网络磁盘归档器(Amanda)备份服务
    11371pgpkeyserver良好隐私(PGP) / GNU 隐私卫士(GPG)公钥服务器
    11720h323callsigaltH.323 调用信号交替
    13720bprdVeritas NetBackup 请求守护进程(bprd)
    13721bpdbmVeritas NetBackup 数据库管理器(bpdbm)
    13722bpjava-msvcVeritas NetBackup Java / Microsoft Visual C++ (MSVC) 协议
    13724vnetdVeritas 网络工具
    13782bpcdVertias NetBackup
    13783vopiedVeritas VOPIED 协议
    22273wnn6 [wnn4]假名/汉字转换系统
    26000quakeQuake(以及相关的)多人游戏服务器
    26208wnn6-ds 
    33434tracerouteTraceroute 网络跟踪工具
    注:
    /etc/services中的注释如下:端口1236被注册为“bvcontrol”,但是它也被 Gracilis Packeten 远程配置服务器使用。正式名称被列为主要名称,未注册的名称被列为别名。
    在/etc/services中的注释:端口 2600 到 2606 被 zebra 软件包未经注册而使用。主要名称是被注册的名称,被 zebra 使用的未注册名称被列为别名。
    /etc/services 文件中的注释:该端口被注册为 wnn6,但是还在 FreeWnn 软件包中使用了未注册的“wnn4”。

    数据报传递协议端口

    显示了一个和数据报传递协议(DDP)有关的端口列表。DDP 在 AppleTalk 网络上被使用。

    端口号码 / 层名称注释
    1/ddprtmp路由表管理协议
    2/ddpnbp名称绑定协议
    4/ddpechoAppleTalk Echo 协议
    6/ddpzip区块信息协议

    Kerberos(工程 Athena/MIT)端口

    和 Kerberos 网络验证协议相关的端口列表。在标记的地方,v5 代表 Kerberos 版本5协议。注意,这些端口没有在 IANA 注册。

    端口号码 / 层名称注释
    751kerberos_masterKerberos 验证
    752passwd_serverKerberos 口令(kpasswd)服务器
    754krb5_propKerberos v5 从属传播
    760krbupdate [kreg]Kerberos 注册
    1109kpopKerberos 邮局协议(KPOP)
    2053knetdKerberos 多路分用器
    2105ekloginKerberos v5 加密的远程登录(rlogin)

    未注册的端口

    一个未注册的端口列表。这些端口可能被安装在你的红帽企业 Linux 系统上的服务或协议使用,或者它们是在红帽企业 Linux 和运行其它操作系统的机器通信所必需的端口。

    端口号码 / 层名称注释
    15/tcpnetstat网络状态(netstat)
    98/tcplinuxconfLinuxconf Linux 管理工具
    106poppassd邮局协议口令改变守护进程(POPPASSD)
    465/tcpsmtps通过安全套接字层的简单邮件传输协议(SMTPS)
    616/tcpgii使用网关的(选路守护进程)互动界面
    808omirr [omirrd]联机镜像(Omirr)文件镜像服务
    871/tcpsupfileserv软件升级协议(SUP)服务器
    901/tcpswatSamba 万维网管理工具(SWAT)
    953rndcBerkeley 互联网名称域版本9(BIND 9)远程名称守护进程配置工具
    1127sufiledbg软件升级协议(SUP)调试
    1178/tcpskkserv简单假名到汉字(SKK)日文输入服务器
    1313/tcpxtel法国 Minitel 文本信息系统
    1529/tcpsupport [prmsd, gnatsd]GNATS 错误跟踪系统
    2003/tcpcfingerGNU Finger 服务
    2150ninstall网络安装服务
    2988afbackupafbackup 客户-服务器备份系统
    3128/tcpsquidSquid 万维网代理缓存
    3455prsvpRSVP 端口
    5432postgresPostgreSQL 数据库
    4557/tcpfaxFAX 传输服务(旧服务)
    4559/tcphylafaxHylaFAX 客户-服务器协议(新服务)
    5232sgi-dglSGI 分布式图形库
    5354noclogNOCOL 网络操作中心记录守护进程(noclogd)
    5355hostmonNOCOL 网络操作中心主机监视
    5680/tcpcannaCanna 日文字符输入界面
    6010/tcpx11-ssh-offset安全 Shell(SSH)X11 转发偏移
    6667ircd互联网中继聊天守护进程(ircd)
    7100/tcpxfsX 字体服务器(XFS)
    7666/tcptircproxyTircproxy IRC 代理服务
    8008http-alt超文本传输协议(HTTP)的另一选择
    8080webcache万维网(WWW)缓存服务
    8081tproxy透明代理
    9100/tcpjetdirect [laserjet, hplj]Hewlett-Packard (HP) JetDirect 网络打印服务
    9359mandelspawn [mandelbrot]用于 X 窗口系统的并行 Mandelbrot 生成程序
    10081kamanda使用 Kerberos 的 Amanda 备份服务
    10082/tcpamandaidxAmanda 备份服务
    10083/tcpamidxtapeAmanda 备份服务
    20011isdnlog综合业务数字网(ISDN)登录系统
    20012vboxdISDN 音箱守护进程(vboxd)
    22305/tcpwnn4_KrkWnn 韩文输入系统
    22289/tcpwnn4_CncWnn 中文输入系统
    22321/tcpwnn4_TwtWnn 中文输入系统(台湾)
    24554binkpBinkley TCP/IP Fidonet 邮寄程序守护进程
    27374asp地址搜索协议
    60177tfidoIfmail FidoNet 兼容邮寄服务
    60179fidoFidoNet 电子邮件和新闻网络
  • yarn : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本

    yarn : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本

    问题描述

    yarn : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policies。

    解决办法

    搜索powershell,右键以管理员身份运行

    输入:set-ExecutionPolicy RemoteSigned

    然后:输入 y

    关闭命令窗口 即可

  • PHP 缩图利器:TimThumb 生成网页截图

    PHP 缩图利器:TimThumb 生成网页截图

    TimThumb 是一个非常简洁方便用于裁图的 PHP 程序,只要给他设置一些参数,它就可以生成缩略图。现在很多 WordPress 主题中,都使用 TimThumb 这个 PHP 类库进行缩略图的处理。

    TimThumb 的使用

    TimThumb 是对服务器有要求的,需要服务器支持 GD 库,现在一般的主机都支持,然后到 TimThumb 官网下载脚本并上传到服务器,在和 TimThumb 同一个目录下,新建一个 cache 文件夹,并且设置 cache 文件夹为可写。

    TimThumb 这个 这个 PHP 裁图脚本使用起来非常简单,下面就是一个简单的图片裁剪案例:

    timthumb.php?src=my_image.jpg&h=150&w=150&zc=1
    它将图片裁剪成宽为150,高为150。如果你不想裁剪,只是压缩为,将 zc 参数设置为 0。

    除了这些参数之外,TimThumb 还有很多参数可以让你设置。

    另外 TimThunb 还支持滤镜,之外外部链接等。总之是一个非常强大图片缩略图处理库。

    TimThumb 的缺点

    由于 TimThumb 是通过参数的方式来设置缩略图的大小和其他一些属性,所以它的图片没法进行伪静态处理,所以生成的图片也无法进行 CDN 加速。并且 TimThumb 裁图时候是需要消耗一定服务器资源的。

    而七牛云存储服务支持图片缩略、裁剪、旋转、转化等功能,所以如果能够基于七牛的云存储服务开发一款 WordPress 缩略图功能,将是非常方便并高效的方式。尽请期待。 ?

    访问地址为:http://localhost/timthumb.php?src=http://localhost/200.jpg&w=200&h=300&q=100&f=3,9|4,2&s=1&ct=1

    参数都是get提交的,可选参数和说明如下:

    src : 需要进行图片缩放的源图片地址,或者是需要进行截图操作的网页地址

    webshot: 如果此值为真则进行截图操作

    w : 生成图片的宽度,如果宽度或高度只设置了一个值,则根据其中一个值进行等比缩放

    h : 生成图片的高度,如果高度和宽度都没有指定,则默认为100*100

    zc : 生成图片的缩放模式,可选值0, 1, 2, 3, 默认为1,每个值的不同之处可看下面文件的第100行注释

    q : 生成图片的质量,默认90

    a : 超出部分的裁剪位置,和缩放模式有关,可选值t, b, l, r, 默认为从顶部裁剪

    f : 需要对生成后的图片使用一些过滤器的话,则在这里传不同过滤器的代码和值,具体操作方法可见下面文件的第821行注解

    s : 是否对生产的图片进行锐化处理

    cc : 生成图片的背景画布颜色

    ct : 生成png图片时背景是否透明

    timthumb.php逐行注释功能作用 中文版

    <?php
    //定义版本信息
    define ('VERSION', '2.8.10');
    //如果有配置文件,则加载timthumb-config.php,没有的话使用下面的值
    if( file_exists(dirname(__FILE__) . '/timthumb-config.php')){
      require_once('timthumb-config.php');
    }
    //调试日志记录到web服务器日志中
    if(! defined('DEBUG_ON') ){
      define ('DEBUG_ON', false);
    }
    //调试级别,高于这个值的level都不会记录,1最低,3最高
    if(! defined('DEBUG_LEVEL') ){
      define ('DEBUG_LEVEL', 1);
    }
    //最大占用内存限制30M
    if(! defined('MEMORY_LIMIT') ){
      define ('MEMORY_LIMIT', '30M');
    }
    //关闭仿盗链
    if(! defined('BLOCK_EXTERNAL_LEECHERS') ){
      define ('BLOCK_EXTERNAL_LEECHERS', false);
    } 					
    // 允许从外部获取<strong><strong>图片</strong></strong>
    if(! defined('ALLOW_EXTERNAL') ){
      define ('ALLOW_EXTERNAL', TRUE);
    }
    //允许获取所有外部站点url
    if(! defined('ALLOW_ALL_EXTERNAL_SITES') ){
      define ('ALLOW_ALL_EXTERNAL_SITES', false);
    }
    //启用文件缓存
    if(! defined('FILE_CACHE_ENABLED') ){
      define ('FILE_CACHE_ENABLED', TRUE);
    }
    //文件缓存更新时间,s
    if(! defined('FILE_CACHE_TIME_BETWEEN_CLEANS')){
      define ('FILE_CACHE_TIME_BETWEEN_CLEANS', 86400);
    }
    //文件缓存生存时间,s,过了这个时间的缓存文件就会被删除
    if(! defined('FILE_CACHE_MAX_FILE_AGE') ){
      define ('FILE_CACHE_MAX_FILE_AGE', 86400);
    }
    //缓存文件后缀
    if(! defined('FILE_CACHE_SUFFIX') ){
      define ('FILE_CACHE_SUFFIX', '.timthumb.txt');
    }
    //缓存文件前缀
    if(! defined('FILE_CACHE_PREFIX') ){
      define ('FILE_CACHE_PREFIX', 'timthumb');
    }
    //缓存文件目录,留空则使用系统临时目录(推荐)
    if(! defined('FILE_CACHE_DIRECTORY') ){
      define ('FILE_CACHE_DIRECTORY', './cache');
    }
    //<strong><strong>图片</strong></strong>最大尺寸,此脚本最大能<strong>处理</strong>10485760字节的<strong><strong>图片</strong></strong>,也就是10M
    if(! defined('MAX_FILE_SIZE') ){
      define ('MAX_FILE_SIZE', 10485760);
    }  
    //CURL的超时时间
    if(! defined('CURL_TIMEOUT') ){
      define ('CURL_TIMEOUT', 20);
    }
    //清理错误缓存的时间
    if(! defined('WAIT_BETWEEN_FETCH_ERRORS') ){
      define ('WAIT_BETWEEN_FETCH_ERRORS', 3600);
    }
    //浏览器缓存时间
    if(! defined('BROWSER_CACHE_MAX_AGE') ){
      define ('BROWSER_CACHE_MAX_AGE', 864000);
    }
    //关闭所有浏览器缓存
    if(! defined('BROWSER_CACHE_DISABLE') ){
      define ('BROWSER_CACHE_DISABLE', false);
    }
    //最大图像宽度
    if(! defined('MAX_WIDTH') ){
      define ('MAX_WIDTH', 1500);
    }
    //最大图像高度
    if(! defined('MAX_HEIGHT') ){
      define ('MAX_HEIGHT', 1500);
    }
    //404错误时显示的提示<strong><strong>图片</strong></strong>地址,设置测值则不会显示具体的错误信息
    if(! defined('NOT_FOUND_IMAGE') ){
      define ('NOT_FOUND_IMAGE', '');
    }
    //其他错误时显示的提示<strong><strong>图片</strong></strong>地址,设置测值则不会显示具体的错误信息
    if(! defined('ERROR_IMAGE') ){
      define ('ERROR_IMAGE', '');
    }
    //PNG<strong><strong>图片</strong></strong>背景颜色,使用false代表透明
    if(! defined('PNG_IS_TRANSPARENT') ){
      define ('PNG_IS_TRANSPARENT', FALSE);
    }
    //默认<strong><strong>图片</strong></strong>质量
    if(! defined('DEFAULT_Q') ){
      define ('DEFAULT_Q', 90);
    }
    //默认 缩放/裁剪 模式,0:根据传入的值进行缩放(不裁剪), 1:以最合适的比例裁剪和调整大小(裁剪), 2:按比例调整大小,并添加边框(裁剪),2:按比例调整大小,不添加边框(裁剪)
    if(! defined('DEFAULT_ZC') ){
      define ('DEFAULT_ZC', 1);
    }
    //默认需要对<strong><strong>图片</strong></strong>进行的<strong>处理</strong>操作,可选值和参数格式请参看processImageAndWriteToCache函数中的$filters和$imageFilters的注释
    if(! defined('DEFAULT_F') ){
      define ('DEFAULT_F', '');
    }
    //是否对<strong><strong>图片</strong></strong>进行锐化
    if(! defined('DEFAULT_S') ){
      define ('DEFAULT_S', 0);
    }
    //默认画布颜色
    if(! defined('DEFAULT_CC') ){
      define ('DEFAULT_CC', 'ffffff');
    }
    //以下是<strong><strong>图片</strong></strong>压缩设置,前提是你的主机中有optipng或者pngcrush这两个工具,否则的话不会启用此功能
    //此功能只对png<strong><strong>图片</strong></strong>有效
    if(! defined('OPTIPNG_ENABLED') ){
      define ('OPTIPNG_ENABLED', false);
    }  
    if(! defined('OPTIPNG_PATH') ){
      define ('OPTIPNG_PATH', '/usr/bin/optipng');
    } //优先使用optipng,因为有更好的压缩比 
    if(! defined('PNGCRUSH_ENABLED') ){
      define ('PNGCRUSH_ENABLED', false);
    } 
    if(! defined('PNGCRUSH_PATH') ){
      define ('PNGCRUSH_PATH', '/usr/bin/pngcrush');
    } //optipng不存在的话,使用pngcrush
    //<strong><strong>图片</strong></strong>压缩设置结束
    
    /* 
     * * 以下是网站截图配置
     * 首先,网站截图需要root权限
     * Ubuntu 上使用网站截图的步骤:
     *  1.用这个命令安装Xvfb  sudo apt-get install subversion libqt4-webkit libqt4-dev g++ xvfb
     *  2.新建一个文件夹,并下载下面的源码
     *  3.用这个命令下载最新的CutyCapt  svn co https://cutycapt.svn.sourceforge.net/svnroot/cutycapt
     *  4.进入CutyCapt文件夹
     *  5.编译并安装CutyCapt
     *  6.尝试运行以下命令:  xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url="http://markmaunder.com/" --out=test.png
     *  7.如果生成了一个 test.php的<strong><strong>图片</strong></strong>,证明一切正常,现在通过浏览器试试,访问下面的地址:http://yoursite.com/path/to/timthumb.php?src=http://markmaunder.com/&webshot=1
     *
     * 需要注意的地方:
     *  1.第一次webshot加载时,需要数秒钟,之后加载就很快了
     *
     * 高级用户:
     *  1.如果想提速大约25%,并且你了解linux,可以运行以下命令:
     *  nohup Xvfb :100 -ac -nolisten tcp -screen 0, 1024x768x24 > /dev/null 2>&1 &
     *  并设置 WEBSHOT_XVFB_RUNNING 的值为true
     *
     * */
    //测试的功能,如果设置此值为true, 并在查询字符串中加上webshot=1,会让脚本返回浏览器的截图,而不是获取图像
    if(! defined('WEBSHOT_ENABLED') ){
      define ('WEBSHOT_ENABLED', false);
    }
    //定义CutyCapt地址
    if(! defined('WEBSHOT_CUTYCAPT') ){
      define ('WEBSHOT_CUTYCAPT', '/usr/local/bin/CutyCapt');
    }
    //Xvfb地址
    if(! defined('WEBSHOT_XVFB') ){
      define ('WEBSHOT_XVFB', '/usr/bin/xvfb-run');
    }
    //截图屏幕宽度1024
    if(! defined('WEBSHOT_SCREEN_X') ){
      define ('WEBSHOT_SCREEN_X', '1024');
    }
    //截图屏幕高度768
    if(! defined('WEBSHOT_SCREEN_Y') ){
      define ('WEBSHOT_SCREEN_Y', '768');
    }
    //色深,作者说他只测试过24
    if(! defined('WEBSHOT_COLOR_DEPTH') ){
      define ('WEBSHOT_COLOR_DEPTH', '24');	
    }
    //截图格式
    if(! defined('WEBSHOT_IMAGE_FORMAT') ){
      define ('WEBSHOT_IMAGE_FORMAT', 'png');
    }
    //截图超时时间,单位s
    if(! defined('WEBSHOT_TIMEOUT') ){
      define ('WEBSHOT_TIMEOUT', '20');
    }
    //user_agent头
    if(! defined('WEBSHOT_USER_AGENT') ){
      define ('WEBSHOT_USER_AGENT', "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18");
    }
    //是否启用JS
    if(! defined('WEBSHOT_JAVASCRIPT_ON') ){
      define ('WEBSHOT_JAVASCRIPT_ON', true);
    }
    //是否启用java
    if(! defined('WEBSHOT_JAVA_ON') ){
      define ('WEBSHOT_JAVA_ON', false);
    }
    //开启flash和其他插件
    if(! defined('WEBSHOT_PLUGINS_ON') ){
      define ('WEBSHOT_PLUGINS_ON', true);
    }
    //代理服务器
    if(! defined('WEBSHOT_PROXY') ){
      define ('WEBSHOT_PROXY', '');	
    }
    //如果运行了XVFB,此项设为true
    if(! defined('WEBSHOT_XVFB_RUNNING') ){
      define ('WEBSHOT_XVFB_RUNNING', false);
    }
    // 如果 ALLOW_EXTERNAL 的值为真 并且 ALLOW_ALL_EXTERNAL_SITES 的值为假,那么截图的<strong><strong>图片</strong></strong>只能从下面这些数组中的域和子域进行
    if(! isset($ALLOWED_SITES)){
      $ALLOWED_SITES = array (
        'flickr.com',
        'staticflickr.com',
        'picasa.com',
        'img.youtube.com',
        'upload.wikimedia.org',
        'photobucket.com',
        'imgur.com',
        'imageshack.us',
        'tinypic.com',
      );
    }
    /*截图配置结束*/
    // -------------------------------------------------------------
    // -------------------------- 配置结束 ------------------------
    // -------------------------------------------------------------
    
    timthumb::start();
    class timthumb {
    	protected $src = "";  //需要获取的<strong><strong>图片</strong></strong>url
    	protected $is404 = false;  //404错误码
    	protected $docRoot = "";  //服务器文档根目录
    	protected $lastURLError = false; //上一次请求外部url的错误信息
    	protected $localImage = ""; //如果请求的url是本地<strong><strong>图片</strong></strong>,则为本地<strong><strong>图片</strong></strong>的地址
    	protected $localImageMTime = 0;  //本地<strong><strong>图片</strong></strong>的修改时间
    	protected $url = false;  //用parse_url解析src后的数组
            protected $myHost = "";  //本机域名
    	protected $isURL = false;  //是否为外部<strong><strong>图片</strong></strong>地址
    	protected $cachefile = ''; //缓存文件地址
    	protected $errors = array();  //错误信息列表
    	protected $toDeletes = array(); //析构函数中需要删除的资源列表
    	protected $cacheDirectory = ''; //缓存地址
    	protected $startTime = 0;  //开始时间
    	protected $lastBenchTime = 0; //上一次debug完成的时间
    	protected $cropTop = false;  //是否启用裁剪
    	protected $salt = "";  //文件修改时间和inode连接的字符串的盐值
    	protected $fileCacheVersion = 1; //文件缓存版本,当这个类升级或者被更改时,这个值应该改变,从而重新生成缓存
    	protected $filePrependSecurityBlock = "<?php die('Execution denied!'); //"; //缓存文件安全头,防止直接访问
    	protected static $curlDataWritten = 0;  //将curl获取到的数据写入缓存文件的长度
    	protected static $curlFH = false;  //curl请求成功后要将获取到的数据写到此文件内
    	/*外部调用接口*/
    	public static function start(){
    	  	//实例化模型
    	  	$tim = new timthumb();
    		//检查实例化模型时是否有错误
    		$tim->handleErrors();
    		//此函数为空,用做自定义的数据验证
    		$tim->securityChecks();
    		//尝试读取浏览器缓存
    		if($tim->tryBrowserCache()){
    		  	//成功的话就输出缓存
    			exit(0);
    		}
    		//检测错误
    		$tim->handleErrors();
    		//如果启用了文件缓存,并且读取服务端缓存
    		if(FILE_CACHE_ENABLED && $tim->tryServerCache()){
    		  	//成功的话输出缓存
    			exit(0);
    		}
    		//检测读取服务端缓存时的错误
    		$tim->handleErrors();
    		//生成和<strong>处理</strong><strong><strong>图片</strong></strong>主函数
    		$tim->run();
    		//检测<strong><strong>图片</strong></strong>生成和<strong>处理</strong>时的错误
    		$tim->handleErrors();
    		//程序执行完毕运行析构方法并退出
    		exit(0);
    	}
    	/*构造方法,用来获取和设置一些基本属性*/
    	public function __construct(){
    	  	//将允许的域设为全局变量
    	  	global $ALLOWED_SITES;
    		//记录开始时间
    		$this->startTime = microtime(true);
    		//设置时区
    		date_default_timezone_set('UTC');
    		//写日志,记录请求IP和请求URL
    		$this->debug(1, "Starting new request from " . $this->getIP() . " to " . $_SERVER['REQUEST_URI']);
    		//获取服务器文档根目录
    		$this->calcDocRoot();
    		//获取文件的修改时间和inode,inode只在linux系统下有效
    		$this->salt = @filemtime(__FILE__) . '-' . @fileinode(__FILE__);
    		//记录salt信息,级别3
    		$this->debug(3, "Salt is: " . $this->salt);
    		//如果定义了缓存文件地址
    		if(FILE_CACHE_DIRECTORY){
    		  	//如果这个地址不存在,或为非目录
    		  	if(! is_dir(FILE_CACHE_DIRECTORY)){
    		    		//建立这个目录
    			  	@mkdir(FILE_CACHE_DIRECTORY);
    				//如果建立失败
    				if(! is_dir(FILE_CACHE_DIRECTORY)){
    				  	//记录错误信息,停止执行
    					$this->error("Could not create the file cache directory.");
    					return false;
    				}
    			}
    			//将缓存地址写入成员属性
    			$this->cacheDirectory = FILE_CACHE_DIRECTORY;
    			//在缓存目录下创建一个index.html文件,防止列目录
    			if (!touch($this->cacheDirectory . '/index.html')) {
    			  	//如果出错,记录错误信息
    				$this->error("Could not create the index.html file - to fix this create an empty file named index.html file in the cache directory.");
    			}
    		//如果没定义缓存文件地址,则用系统的临时文件目录做为缓存文件目录
    		} else {
    			$this->cacheDirectory = sys_get_temp_dir();
    		}
    		//进行缓存检查,清除过期缓存
    		$this->cleanCache();
    		//记录本机域名
    		$this->myHost = preg_replace('/^www./i', '', $_SERVER['HTTP_HOST']);
    		//获取<strong><strong>图片</strong></strong>地址,此地址应该由$_GET中的src参数传递
    		$this->src = $this->param('src');
    		//此数组是解析src后的结果,包括scheme,host,port,user,pass,path,query,fragment其中一个或多个值
    		$this->url = parse_url($this->src);
    		//如果<strong><strong>图片</strong></strong>地址是本机的,则删除<strong><strong>图片</strong></strong>url中本机的域名部分
    		$this->src = preg_replace('/https?://(?:www.)?' . $this->myHost . '/i', '', $this->src);
    		//如果<strong><strong>图片</strong></strong>地址的长度小于3,则是无效地址
    		if(strlen($this->src) <= 3){
    		  	//添加错误信息
    			$this->error("No image specified");
    			return false;
    		}
    		//如果开启了防盗链,并且存在来源地址,也就是HTTP_REFERER头,并且来源地址不是本机,则进行防盗链<strong>处理</strong>
    		if(BLOCK_EXTERNAL_LEECHERS && array_key_exists('HTTP_REFERER', $_SERVER) && (! preg_match('/^https?://(?:www.)?' . $this->myHost . '(?:$|/)/i', $_SERVER['HTTP_REFERER']))){
    			//此base64编码的内容是一张显示 No Hotlinking的<strong><strong>图片</strong></strong>
    		  	$imgData = base64_decode("R0lGODlhUAAMAIAAAP8AAP///yH5BAAHAP8ALAAAAABQAAwAAAJpjI+py+0Po5y0OgAMjjv01YUZnOGplhWXfNa6JCLnWkXplrcBmW+spbwvaVr/cDyg7IoFC2KbYVC2NQ5MQ4ZNao9Ynzjl9ScNYpnebnDULB3RP6JuPuaGfuuV4fumf8PuvqFyhYtjdoeFgAADs=");
    			//显示内容为gif<strong><strong>图片</strong></strong>
    			header('Content-Type: image/gif');
    			//内容长度
    			header('Content-Length: ' . sizeof($imgData));
    			//无<strong>网页</strong>缓存
    			header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    			//兼容http1.0和https
    			header("Pragma: no-cache");
    			//内容立即过期
    			header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
    			//输出<strong><strong>图片</strong></strong>
    			echo $imgData;
    			return false;
    			//退出脚本
    			exit(0);
    		}
    		//如果此时的src属性包含http等字符,说明是外部链接
    		if(preg_match('/^https?://[^/]+/i', $this->src)){
    		  	//写日志,说明这个链接是外部的,级别2
    		  	$this->debug(2, "Is a request for an external URL: " . $this->src);
    			//将isURL设为true,说明是外部url
    			$this->isURL = true;
    		//如果不包含的话,说明是内部链接
    		} else {
    			$this->debug(2, "Is a request for an internal file: " . $this->src);
    		}
    		//如果<strong><strong>图片</strong></strong>的src是外部网站,并且配置文件不允许从外部获取<strong><strong>图片</strong></strong>,则退出
    		if($this->isURL && (! ALLOW_EXTERNAL)){
    			$this->error("You are not allowed to fetch images from an external website.");
    			return false;
    		}
    		//如果允许从外部网站获取<strong><strong>图片</strong></strong>
    		if($this->isURL){
    		  	//并且配置文件允许从所有的外部网站获取<strong><strong>图片</strong></strong>
    		  	if(ALLOW_ALL_EXTERNAL_SITES){
    				//写日志,允许从外部网站取回<strong><strong>图片</strong></strong>,级别2
    			  	$this->debug(2, "Fetching from all external sites is enabled.");
    			//如果配置文件不允许从所有的外部网站获取<strong><strong>图片</strong></strong>
    			} else {
    			  	//写日志,只能从指定的外部网站获取<strong><strong>图片</strong></strong>,级别2
    			  	$this->debug(2, "Fetching only from selected external sites is enabled.");
    				//此为验证位,默认为false
    				$allowed = false;
    				//遍历配置文件中允许站点的列表
    				foreach($ALLOWED_SITES as $site){
    				  	//这里对<strong><strong>图片</strong></strong>的url跟允许访问站点的列表进行验证,前面的条件对应的是有主机名的,后面的内容对应的是没有主机名的,写的很精巧
    				  	if ((strtolower(substr($this->url['host'],-strlen($site)-1)) === strtolower(".$site")) || (strtolower($this->url['host'])===strtolower($site))) {
    						//通过验证则写一条日志,验证成功,级别3
    					  	$this->debug(3, "URL hostname {$this->url['host']} matches $site so allowing.");
    						//验证位为true
    						$allowed = true;
    					}
    				}
    				//如果没通过验证, 写错误信息并退出
    				if(! $allowed){
    					return $this->error("You may not fetch images from that site. To enable this site in timthumb, you can either add it to $ALLOWED_SITES and set ALLOW_EXTERNAL=true. Or you can set ALLOW_ALL_EXTERNAL_SITES=true, depending on your security needs.");
    				}
    			}
    		}
    		//缓存文件的前缀,如果是内部<strong><strong>图片</strong></strong>,用_int_,外部<strong><strong>图片</strong></strong>用_ext_
    		$cachePrefix = ($this->isURL ? '_ext_' : '_int_');
    		//如果是外部<strong><strong>图片</strong></strong>地址
    		if($this->isURL){
    		  	//得到GET字符串的数组
    		  	$arr = explode('&', $_SERVER ['QUERY_STRING']);
    			//按字母顺序对数组元素排序
    			asort($arr);
    			//生成缓存文件地址  缓存目录 + / + 缓存前缀 + $cachePrefix + 唯一散列值  + 缓存后缀
    			$this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . implode('', $arr) . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
    		//如果是本地<strong><strong>图片</strong></strong>
    		} else {
    		  	//获取本地<strong><strong>图片</strong></strong>地址
    		  	$this->localImage = $this->getLocalImagePath($this->src);
    			//如果获取不到地址
    			if(! $this->localImage){
    			  	//写日志,没有找到此文件,级别1
    			  	$this->debug(1, "Could not find the local image: {$this->localImage}");
    				//记录错误信息
    				$this->error("Could not find the internal image you specified.");
    				//设置404错误信息
    				$this->set404();
    				//终止执行程序
    				return false;
    			}
    			//写日志,记录本地<strong><strong>图片</strong></strong>信息,级别1
    			$this->debug(1, "Local image path is {$this->localImage}");
    			//获取文件修改时间
    			$this->localImageMTime = @filemtime($this->localImage);
    			//生成缓存文件地址,  缓存目录 + / + 缓存前缀 + $cachePrefix + 唯一散列值 + 缓存后缀
    			$this->cachefile = $this->cacheDirectory . '/' . FILE_CACHE_PREFIX . $cachePrefix . md5($this->salt . $this->localImageMTime . $_SERVER ['QUERY_STRING'] . $this->fileCacheVersion) . FILE_CACHE_SUFFIX;
    		}
    		//记录缓存文件地址
    		$this->debug(2, "Cache file is: " . $this->cachefile);
    		//构造函数完成
    		return true;
    	}
    	/*析构方法,删除toDeletes数组中的每一个文件*/
    	public function __destruct(){
    		foreach($this->toDeletes as $del){
    			$this->debug(2, "Deleting temp file $del");
    			@unlink($del);
    		}
    	}
    	/*主函数,通过不同参数调用不同的<strong><strong>图片</strong></strong><strong>处理</strong>函数*/
    	public function run(){
    	  	//如果是外部的<strong><strong>图片</strong></strong>链接
    	  	if($this->isURL){
    			//但是配置文件不允许从外部获取链接
    		  	if(! ALLOW_EXTERNAL){
    				//写日志,说明配置文件禁止访问外部<strong><strong>图片</strong></strong>,级别1
    			  	$this->debug(1, "Got a request for an external image but ALLOW_EXTERNAL is disabled so returning error msg.");
    				//写错误记录
    				$this->error("You are not allowed to fetch images from an external website.");
    				//退出执行
    				return false;
    			}
    			//配置文件允许从外部获取链接,则写日志,接着运行,级别3
    			$this->debug(3, "Got request for external image. Starting serveExternalImage.");
    			//如果get了webshot参数并且为真,则进行截图操作
    			if($this->param('webshot')){
    			  	//如果配置文件允许截图
    			  	if(WEBSHOT_ENABLED){
    			    		//写日志,说明要进行截图操作,级别3
    				  	$this->debug(3, "webshot param is set, so we're going to take a webshot.");
    					//截图操作
    					$this->serveWebshot();
    				//如果配置文件不允许截图
    				} else {
    				  	//记录错误信息并退出
    					$this->error("You added the webshot parameter but webshots are disabled on this server. You need to set WEBSHOT_ENABLED == true to enable webshots.");
    				}
    			//如果不存在sebshot参数或为假
    			} else {
    			  	//写日志,记录不进行截图操作,级别3
    			  	$this->debug(3, "webshot is NOT set so we're going to try to fetch a regular image.");
    				//从外部URL获得<strong><strong>图片</strong></strong>并<strong>处理</strong>
    				$this->serveExternalImage();
    			}
    		//否则的话就是内部<strong><strong>图片</strong></strong>
    		} else {
    		  	//写日志,记录是内部<strong><strong>图片</strong></strong>,级别3
    		  	$this->debug(3, "Got request for internal image. Starting serveInternalImage()");
    			//获得内部<strong><strong>图片</strong></strong>并<strong>处理</strong>
    			$this->serveInternalImage();
    		}
    		//程序执行完毕
    		return true;
    	}
    	/*此函数用来<strong>处理</strong>错误*/
    	protected function handleErrors(){
    	  	//如果错误列表中有内容
    	  	if($this->haveErrors()){
    			//首先检测404错误,如果设置了404<strong><strong>图片</strong></strong>地址并且的确有404错误
    		  	if(NOT_FOUND_IMAGE && $this->is404()){
    				//那么输出错误<strong><strong>图片</strong></strong>,并退出脚本
    				if($this->serveImg(NOT_FOUND_IMAGE)){
    				  	exit(0);
    				//输出失败的话记录错误信息
    				} else {
    					$this->error("Additionally, the 404 image that is configured could not be found or there was an error serving it.");
    				}
    			}
    			//如果没有404错误,并且定义了错误<strong><strong>图片</strong></strong>,那么输出此<strong><strong>图片</strong></strong>
    			if(ERROR_IMAGE){
    			  	//输出其他错误提示<strong><strong>图片</strong></strong>,并退出脚本
    				if($this->serveImg(ERROR_IMAGE)){
    				  	exit(0);
    				//输出失败的话记录错误信息
    				} else {
    					$this->error("Additionally, the error image that is configured could not be found or there was an error serving it.");
    				}
    			}
    			//如果上面两个常量都没定义,则根据模板输出详细错误信息
    			$this->serveErrors(); 
    			exit(0); 
    		}
    		//没有错误的话返回假
    		return false;
    	}
    	/*此函数用来读取浏览器缓存文件,前提是浏览器缓存的文件有效,具体的实现请看函数内部*/
    	protected function tryBrowserCache(){
    	  	//如果配置文件关闭了所有浏览器缓存,则写日志,并返回假
    	  	if(BROWSER_CACHE_DISABLE){ 
    		  	$this->debug(3, "Browser caching is disabled"); return false; 
    		}
    		//如果浏览器记录了页面上次修改的时间
    		if(!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) ){
    		  	//写日志,记录,级别3
    		  	$this->debug(3, "Got a conditional get");
    			//缓存文件最后修改时间
    			$mtime = false;
    			//如果缓存地址无效
    			if(! is_file($this->cachefile)){
    				//说明没有缓存,返回假
    				return false;
    			}
    			//如果存在本地<strong><strong>图片</strong></strong>修改时间,也就是说所请求的<strong><strong>图片</strong></strong>是本机的
    			if($this->localImageMTime){
    			  	//缓存文件修改时间设置为本地<strong><strong>图片</strong></strong>修改时间
    			  	$mtime = $this->localImageMTime;
    				//写日志,记录实际文件修改时间,级别3
    				$this->debug(3, "Local real file's modification time is $mtime");
    			//如果请求的<strong><strong>图片</strong></strong>不是本地的
    			} else if(is_file($this->cachefile)){
    			  	//获取缓存文件修改时间
    			  	$mtime = @filemtime($this->cachefile);
    				//写日志,记录缓存文件修改时间,级别3
    				$this->debug(3, "Cached file's modification time is $mtime");
    			}
    			//如果没有获取到缓存文件最后修改时间,说明没有缓存,退出
    			if(! $mtime){ return false; }
    			//将浏览器中存储的上次修改时间转为时间戳
    			$iftime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    			//写日志,记录UNIX时间戳,级别3
    			$this->debug(3, "The conditional get's if-modified-since unixtime is $iftime");
    			//如果这个时间小于1秒,说明值无效,退出
    			if($iftime < 1){
    			  	//写日志,记录此值无效
    				$this->debug(3, "Got an invalid conditional get modified since time. Returning false.");
    				return false;
    			}
    			//如果浏览器存储的时间小于实际缓存文件的最后修改时间,也就是说距上次访问后,文件被更改了,要重新请求页面
    			if($iftime < $mtime){
    			  	//写日志,记录文件已被更改,级别3
    				$this->debug(3, "File has been modified since last fetch.");
    				return false;
    			//否则就不用重新请求页面,直接读取缓存
    			} else {
    			  	//写日志,记录缓存有效,直接读取缓存,级别3
    			  	$this->debug(3, "File has not been modified since last get, so serving a 304.");
    				//设置HTTP头响应码为304
    				header ($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
    				//记录此次操作,级别1
    				$this->debug(1, "Returning 304 not modified");
    				//读取成功返回真
    				return true;
    			}
    		}
    		//没有读取到缓存,返回假
    		return false;
    	}
    	/*此函数用来运行缓存文件的GC和读取服务器上的缓存文件*/
    	protected function tryServerCache(){
    	  	//写日志,记录将读取服务端缓存,级别3
    	  	$this->debug(3, "Trying server cache");
    	  	//如果缓存文件存在
    		if(file_exists($this->cachefile)){
    		  	//写日志,记录缓存文件存在
    		  	$this->debug(3, "Cachefile {$this->cachefile} exists");
    			//如果请求的是外部<strong><strong>图片</strong></strong>地址
    			if($this->isURL){
    			  	//写日志,记录这是一次外部请求,级别3
    			  	$this->debug(3, "This is an external request, so checking if the cachefile is empty which means the request failed previously.");
    				//如果缓存文件的大小小于1,也就是说是一个无效的缓存文件
    				if(filesize($this->cachefile) < 1){
    				  	//写日志,记录这是一个空的缓存文件,级别3
    					$this->debug(3, "Found an empty cachefile indicating a failed earlier request. Checking how old it is.");
    					//如果已到了配置文件中清理无效缓存的时间
    					if(time() - @filemtime($this->cachefile) > WAIT_BETWEEN_FETCH_ERRORS){
    					  	//写日志,记录这次删除操作,级别3
    					  	$this->debug(3, "File is older than " . WAIT_BETWEEN_FETCH_ERRORS . " seconds. Deleting and returning false so app can try and load file.");
    						//删除此缓存文件
    						@unlink($this->cachefile);
    						//返回假,说明没有读取到服务端缓存
    						return false;
    					//否则,空的缓存文件说明上次请求失败,所以要写错误记录
    					} else {
    					  	//写日志,记录空的缓存文件依然有效,级别3
    					  	$this->debug(3, "Empty cachefile is still fresh so returning message saying we had an error fetching this image from remote host.");
    						//设置404错误
    						$this->set404();
    						//设置错误信息
    						$this->error("An error occured fetching image.");
    						//返回假代表没有得到缓存
    						return false; 
    					}
    				}
    			//否则就是正确的缓存文件
    			} else {
    			  	//写日志,记录将要直接读取缓存文件,级别3
    				$this->debug(3, "Trying to serve cachefile {$this->cachefile}");
    			}
    			//如果输出图像缓存成功
    			if($this->serveCacheFile()){
    			  	//写日志,记录缓存文件信息,级别3
    				$this->debug(3, "Succesfully served cachefile {$this->cachefile}");
    				return true;
    			//如果不成功
    			} else {
    			  	//写日志,记录错误信息,级别3
    				$this->debug(3, "Failed to serve cachefile {$this->cachefile} - Deleting it from cache.");
    				//删除此无效缓存,以便下次请求能重新创建
    				@unlink($this->cachefile);
    				//同样返回真,因为在serverCacheFile已经记录了错误信息
    				return true;
    			}
    		}
    	}
    	/*此函数用来记录错误信息*/
    	protected function error($err){
    	  	//写记录,记录错误信息,级别3
    	  	$this->debug(3, "Adding error message: $err");
    		//记录到错误信息数组
    		$this->errors[] = $err;
    		return false;
    	}
    	/*测函数用来检测存储错误信息的数组中是否有内容,也就是说在上一个操作中,是否有错误*/
    	protected function haveErrors(){
    		if(sizeof($this->errors) > 0){
    			return true;
    		}
    		return false;
    	}
    	/*此函数输出已存储的错误信息*/
    	protected function serveErrors(){
    	  	//设置http头
    	  header ($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
    	  	//循环输出错误列表信息
    		$html = '<ul>';
    		foreach($this->errors as $err){
    			$html .= '<li>' . htmlentities($err) . '</li>';
    		}
    		$html .= '</ul>';
    		//输出其他错误信息
    		echo '<h1>A TimThumb error has occured</h1>The following error(s) occured:<br />' . $html . '<br />';
    		echo '<br />Query String : ' . htmlentities ($_SERVER['QUERY_STRING']);
    		echo '<br />TimThumb version : ' . VERSION . '</pre>';
    	}
    	/*此函数用来读取本地<strong><strong>图片</strong></strong>*/
    	protected function serveInternalImage(){
    	  	//写日志,记录本地<strong><strong>图片</strong></strong>地址
    	  	$this->debug(3, "Local image path is $this->localImage");
    	  	//如果地址无效
    		if(! $this->localImage){
    		  	//记录此错误,并退出执行
    			$this->sanityFail("localImage not set after verifying it earlier in the code.");
    			return false;
    		}
    		//获取本地<strong><strong>图片</strong></strong>大小
    		$fileSize = filesize($this->localImage);
    		//如果本地<strong><strong>图片</strong></strong>的尺寸超过配置文件的相关设置
    		if($fileSize > MAX_FILE_SIZE){
    		  	//记录错误原因,并退出
    			$this->error("The file you specified is greater than the maximum allowed file size.");
    			return false;
    		}
    		//如果获取到的<strong><strong>图片</strong></strong>尺寸无效
    		if($fileSize <= 0){
    		  	//记录错误并退出
    			$this->error("The file you specified is <= 0 bytes.");
    			return false;
    		}
    		//如果通过了以上验证,则写日志,记录将用processImageAndWriteToCache函数<strong>处理</strong>本地<strong><strong>图片</strong></strong>
    		$this->debug(3, "Calling processImageAndWriteToCache() for local image.");
    		//<strong>处理</strong>成功则从缓存返回<strong><strong>图片</strong></strong>
    		if($this->processImageAndWriteToCache($this->localImage)){
    			$this->serveCacheFile();
    			return true;
    		//失败则返回假
    		} else { 
    			return false;
    		}
    	}
    	/*此函数用来清理缓存*/
    	protected function cleanCache(){
    		//如果定义的缓存时间小于0,则退出
    		if (FILE_CACHE_TIME_BETWEEN_CLEANS < 0) {
    			return;
    		}
    		//写日志,记录清除缓存操作,级别3
    		$this->debug(3, "cleanCache() called");
    		//此文件为记录上次进行清除缓存操作的时间戳文件
    		$lastCleanFile = $this->cacheDirectory . '/timthumb_cacheLastCleanTime.touch';
    		
    		//如果上面定义的文件不存在,说明这是第一次进行清除缓存操作,创建此文件并返回空即可
    		if(! is_file($lastCleanFile)){
    		  	//写日志,记录创建文件,级别1
    		  	$this->debug(1, "File tracking last clean doesn't exist. Creating $lastCleanFile");
    			//创建此文件
    			if (!touch($lastCleanFile)) {
    			  	//失败的话报错并退出
    				$this->error("Could not create cache clean timestamp file.");
    			}
    			return;
    		}
    		//如果已超过缓存时间
    		if(@filemtime($lastCleanFile) < (time() - FILE_CACHE_TIME_BETWEEN_CLEANS) ){
    		  	//写日志,记录下面进行的清除缓存操作
    			$this->debug(1, "Cache was last cleaned more than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago. Cleaning now.");
    			//创建新的清除缓存时间戳文件
    			if (!touch($lastCleanFile)) {
    			  	//失败的话记录错误信息
    				$this->error("Could not create cache clean timestamp file.");
    			}
    			//此数组存的是所有缓存文件,根据前面定义的缓存文件目录和缓存文件后缀得到的
    			$files = glob($this->cacheDirectory . '/*' . FILE_CACHE_SUFFIX);
    			//如果有缓存文件
    			if ($files) {
    			  	//计算当前时间和缓存最大生存时间的差值,用于下面判断缓存文件是否删除
    			  	$timeAgo = time() - FILE_CACHE_MAX_FILE_AGE;
    				//遍历缓存文件数组
    				foreach($files as $file){
    				  	//如果文件创建时间小于上面计算的值,也就是说此缓存文件的死期到了,就删除它
    				  	if(@filemtime($file) < $timeAgo){
    				    		//记录删除缓存文件,级别3
    						$this->debug(3, "Deleting cache file $file older than max age: " . FILE_CACHE_MAX_FILE_AGE . " seconds");
    						@unlink($file);
    					}
    				}
    			}
    			return true;
    		//如果没超过缓存时间,则不用清除
    		} else {
    		  	//写日志,记录不用清除缓存
    			$this->debug(3, "Cache was cleaned less than " . FILE_CACHE_TIME_BETWEEN_CLEANS . " seconds ago so no cleaning needed.");
    		}
    		return false;
    	}
    	/*核心函数,<strong>处理</strong><strong><strong>图片</strong></strong>并写入缓存*/
    	protected function processImageAndWriteToCache($localImage){
    	  	//获取<strong><strong>图片</strong></strong>信息
    	  	$sData = getimagesize($localImage);
    		//图像类型标记
    		$origType = $sData[2];
    		//mime类型
    		$mimeType = $sData['mime'];
    		//写日志,记录传入图像的mime类型
    		$this->debug(3, "Mime type of image is $mimeType");
    		//进行图像mime类型验证,只允许gif , jpg 和 png
    		if(! preg_match('/^image/(?:gif|jpg|jpeg|png)$/i', $mimeType)){
    		  	//如果不是这四种类型,记录错误信息,并退出脚本
    			return $this->error("The image being resized is not a valid gif, jpg or png.");
    		}
    		//<strong><strong>图片</strong></strong><strong>处理</strong>需要GD库支持,这里检测是否安装了GD库
    		if (!function_exists ('imagecreatetruecolor')) {
    		    //没有安装的话推出脚本
    		    return $this->error('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
    		}
    		//如果安装了GD库,并且支持图像过滤器函数imagefilter,且支持IMG_FILTER_NEGATE常量
    		if (function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
    		  	//定义一个过滤器效果数组,后面的数字代表需要额外传入的参数
    		  	$imageFilters = array (
    		    		//负片
    			  	1 => array (IMG_FILTER_NEGATE, 0),
    				//黑白的
    				2 => array (IMG_FILTER_GRAYSCALE, 0),
    				//亮度级别
    				3 => array (IMG_FILTER_BRIGHTNESS, 1),
    				//对比度级别
    				4 => array (IMG_FILTER_CONTRAST, 1),
    				//图像转换为制定颜色
    				5 => array (IMG_FILTER_COLORIZE, 4),
    				//突出边缘
    				6 => array (IMG_FILTER_EDGEDETECT, 0),
    				//浮雕
    				7 => array (IMG_FILTER_EMBOSS, 0),
    				//用高斯算法模糊图像
    				8 => array (IMG_FILTER_GAUSSIAN_BLUR, 0),
    				//模糊图像
    				9 => array (IMG_FILTER_SELECTIVE_BLUR, 0),
    				//平均移除法来达到轮廓效果
    				10 => array (IMG_FILTER_MEAN_REMOVAL, 0),
    				//平滑<strong>处理</strong>
    				11 => array (IMG_FILTER_SMOOTH, 0),
    			);
    		}
    		//生成<strong><strong>图片</strong></strong>宽度,由get中w参数指定,默认为0		
    		$new_width =  (int) abs ($this->param('w', 0));
    		//生成<strong><strong>图片</strong></strong>高度,由get中h参数指定,默认为0
    		$new_height = (int) abs ($this->param('h', 0));
    		//生成<strong><strong>图片</strong></strong>缩放模式,由get中zc参数指定,默认为配置文件中DEFAULT_ZC的值
    		$zoom_crop = (int) $this->param('zc', DEFAULT_ZC);
    		//生成<strong><strong>图片</strong></strong>的质量,由get中q参数指定,默认为配置文件中DEFAULT_Q的值
    		$quality = (int) abs ($this->param('q', DEFAULT_Q));
    		//裁剪的位置
    		$align = $this->cropTop ? 't' : $this->param('a', 'c');
    		//需要进行的<strong><strong>图片</strong></strong><strong>处理</strong>操作,多个过滤器用"|"分割,可选参数请参看$imageFilters处的注释,由于不同的过滤器需要的参数不同,如一个过滤器需要多个参数,多个参数用,分隔。例:1,2|3,1,1  代表对图像分别应用1和3过滤效果,1和3所对应的过滤效果是由$imageFilters数组确定的,其中1号过滤器还需要一个额外的参数,这里传了1,3号过滤器还需要2个额外的参数,这里传了1和1.
    		$filters = $this->param('f', DEFAULT_F);
    		//是否对<strong><strong>图片</strong></strong>进行锐化,由get中s参数指定,默认为配置文件中DEFAULT_S的值
    		$sharpen = (bool) $this->param('s', DEFAULT_S);
    		//生成<strong><strong>图片</strong></strong>的默认背景画布颜色,由get中cc参数指定,默认为配置文件中DEFAULT_CC的值
    		$canvas_color = $this->param('cc', DEFAULT_CC);
    		//生成png<strong><strong>图片</strong></strong>的背景是否透明
    		$canvas_trans = (bool) $this->param('ct', '1');
    		// 如果高度和宽度都没有指定,设置他们为100*100
    		if ($new_width == 0 && $new_height == 0) {
    		    $new_width = 100;
    		    $new_height = 100;
    		}
    		// 限制最大高度和最大宽度
    		$new_width = min ($new_width, MAX_WIDTH);
    		$new_height = min ($new_height, MAX_HEIGHT);
    		// 检测并设置php运行最大占用内存
    		$this->setMemoryLimit();
    		// 打开图像资源
    		$image = $this->openImage ($mimeType, $localImage);
    		//如果打开失败,记录信息并退出脚本
    		if ($image === false) {
    			return $this->error('Unable to open image.');
    		}
    		// 获得原始<strong><strong>图片</strong></strong>,也就是上面打开<strong><strong>图片</strong></strong>的宽和高
    		$width = imagesx ($image);
    		$height = imagesy ($image);
    		$origin_x = 0;
    		$origin_y = 0;
    		// 如果新生成<strong><strong>图片</strong></strong>的宽或高没有指定,则用此等比算法算出高或宽的值
    		if ($new_width && !$new_height) {
    			$new_height = floor ($height * ($new_width / $width));
    		} else if ($new_height && !$new_width) {
    			$new_width = floor ($width * ($new_height / $height));
    		}
    		// 如果缩放模式选择的是3,也就是说get中zc=3或者配置文件中DEFAULT_ZC=3,则进行等比缩放,不裁剪
    		if ($zoom_crop == 3) {
    			$final_height = $height * ($new_width / $width);
    			//根据等比算法设置等比计算后的宽或高
    			if ($final_height > $new_height) {
    				$new_width = $width * ($new_height / $height);
    			} else {
    				$new_height = $final_height;
    			}
    		}
    		// 利用<strong>处理</strong>完毕的长和宽创建新画布,
    		$canvas = imagecreatetruecolor ($new_width, $new_height);
    		//关闭混色模式,也就是把PNG的alpha值保存,从而使背景透明
    		imagealphablending ($canvas, false);
    		//进行默认画布颜色的检测并转换,如果给出的是3个字符长度表示的颜色值
    		if (strlen($canvas_color) == 3) { //if is 3-char notation, edit string into 6-char notation
    		  	//转换为6个字符表示的颜色值
    		  	$canvas_color =  str_repeat(substr($canvas_color, 0, 1), 2) . str_repeat(substr($canvas_color, 1, 1), 2) . str_repeat(substr($canvas_color, 2, 1), 2); 
    		//如果不是3个长度也不是6个长度的字符串,则为非法字符串,设置为默认值
    		} else if (strlen($canvas_color) != 6) {
    			$canvas_color = DEFAULT_CC;
     		}
    		//将上面得到的R 、G 、B 三种颜色值转换为10进制表示
    		$canvas_color_R = hexdec (substr ($canvas_color, 0, 2));
    		$canvas_color_G = hexdec (substr ($canvas_color, 2, 2));
    		$canvas_color_B = hexdec (substr ($canvas_color, 4, 2));
    		// 如果传入<strong><strong>图片</strong></strong>的格式是png,并且配置文件设置png背景颜色为透明,并且在get传入了ct的值为真,那么就设置背景颜色为透明
    		if(preg_match('/^image/png$/i', $mimeType) && !PNG_IS_TRANSPARENT && $canvas_trans){ 
    		  	$color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 127);
    		//反之设置为不透明
    		}else{
    			$color = imagecolorallocatealpha ($canvas, $canvas_color_R, $canvas_color_G, $canvas_color_B, 0);
    		}
    		// 使用分配的颜色填充背景
    		imagefill ($canvas, 0, 0, $color);
    		
    		// 如果缩放模式选择的是2,那么画布的体积是按传入的值创建的,并计算出边框的宽度
    		if ($zoom_crop == 2) {
    		  	//等比缩放的高度
    			$final_height = $height * ($new_width / $width);
    			//如果计算出的等比高度,大于传入的高度
    			if ($final_height > $new_height) {
    				//origin_x等于传入的新高度的二分之一
    			  	$origin_x = $new_width / 2;
    			  	//设置新宽度为等比计算出的值
    				$new_width = $width * ($new_height / $height);
    				//计算出两次origin_x的差值
    				$origin_x = round ($origin_x - ($new_width / 2));
    			//否则,计算出两次origin_y的差值
    			} else {
    				$origin_y = $new_height / 2;
    				$new_height = $final_height;
    				$origin_y = round ($origin_y - ($new_height / 2));
    			}
    		}
    		// 保存图像时保存完整的alpha信息
    		imagesavealpha ($canvas, true);
    		//如果缩放模式选择的是1或2或3
    		if ($zoom_crop > 0) {
    		  	$src_x = $src_y = 0;
    			//<strong><strong>图片</strong></strong>原宽度
    			$src_w = $width;
    			//<strong><strong>图片</strong></strong>原高度
    			$src_h = $height;
    			//<strong><strong>图片</strong></strong>纵横比
    			$cmp_x = $width / $new_width;
    			$cmp_y = $height / $new_height;
    			//裁剪算法
    			if ($cmp_x > $cmp_y) {
    				$src_w = round ($width / $cmp_x * $cmp_y);
    				$src_x = round (($width - ($width / $cmp_x * $cmp_y)) / 2);
    			} else if ($cmp_y > $cmp_x) {
    				$src_h = round ($height / $cmp_y * $cmp_x);
    				$src_y = round (($height - ($height / $cmp_y * $cmp_x)) / 2);
    			}
    			// 根据传入参数算出裁剪的位置
    			if ($align) {
    				if (strpos ($align, 't') !== false) {
    					$src_y = 0;
    				}
    				if (strpos ($align, 'b') !== false) {
    					$src_y = $height - $src_h;
    				}
    				if (strpos ($align, 'l') !== false) {
    					$src_x = 0;
    				}
    				if (strpos ($align, 'r') !== false) {
    					$src_x = $width - $src_w;
    				}
    			}
    			//将图像根据算法进行裁剪,并拷贝到背景<strong><strong>图片</strong></strong>上
    			imagecopyresampled ($canvas, $image, $origin_x, $origin_y, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h);
    		} else {
    			//裁剪模式选择的是0,则不进行裁剪,并生成图像
    			imagecopyresampled ($canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
    		}
    		//如果定义了<strong><strong>图片</strong></strong><strong>处理</strong>操作,并且支持<strong><strong>图片</strong></strong><strong>处理</strong>函数
    		if ($filters != '' && function_exists ('imagefilter') && defined ('IMG_FILTER_NEGATE')) {
    			// 分割每个过滤<strong>处理</strong>
    			$filterList = explode ('|', $filters);
    			foreach ($filterList as $fl) {
    			  	//分割一个过滤操作中的参数
    			  	$filterSettings = explode (',', $fl);
    				//如果所选的过滤操作存在
    				if (isset ($imageFilters[$filterSettings[0]])) {
    					//将所有参数转为int类型
    					for ($i = 0; $i < 4; $i ++) {
    						if (!isset ($filterSettings[$i])) {
    							$filterSettings[$i] = null;
    						} else {
    							$filterSettings[$i] = (int) $filterSettings[$i];
    						}
    					}
    					//根据$imageFilters中定义的每个过滤效果需要的参数的不同,对图像应用过滤器效果
    					switch ($imageFilters[$filterSettings[0]][1]) {
    						case 1:
    							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1]);
    							break;
    						case 2:
    							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2]);
    							break;
    						case 3:
    							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3]);
    							break;
    						case 4:
    							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0], $filterSettings[1], $filterSettings[2], $filterSettings[3], $filterSettings[4]);
    							break;
    						default:
    							imagefilter ($canvas, $imageFilters[$filterSettings[0]][0]);
    							break;
    					}
    				}
    			}
    		}
    		// 如果设置了锐化值,并且系统支持锐化函数,则进行锐化操作
    		if ($sharpen && function_exists ('imageconvolution')) {
    			$sharpenMatrix = array (
    					array (-1,-1,-1),
    					array (-1,16,-1),
    					array (-1,-1,-1),
    					);
    			$divisor = 8;
    			$offset = 0;
    			imageconvolution ($canvas, $sharpenMatrix, $divisor, $offset);
    		}
    		//如果<strong><strong>图片</strong></strong>是PNG或者GIF,则用imagetruecolortopalette来减小他们的体积
    		if ( (IMAGETYPE_PNG == $origType || IMAGETYPE_GIF == $origType) && function_exists('imageistruecolor') && !imageistruecolor( $image ) && imagecolortransparent( $image ) > 0 ){
    			imagetruecolortopalette( $canvas, false, imagecolorstotal( $image ) );
    		}
    		//根据生成的不同<strong><strong>图片</strong></strong>类型,生成<strong><strong>图片</strong></strong>缓存,$imgType的值用于生成安全头
    		$imgType = "";
    		$tempfile = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
    		if(preg_match('/^image/(?:jpg|jpeg)$/i', $mimeType)){ 
    			$imgType = 'jpg';
    			imagejpeg($canvas, $tempfile, $quality); 
    		} else if(preg_match('/^image/png$/i', $mimeType)){ 
    			$imgType = 'png';
    			imagepng($canvas, $tempfile, floor($quality * 0.09));
    		} else if(preg_match('/^image/gif$/i', $mimeType)){
    			$imgType = 'gif';
    			imagegif($canvas, $tempfile);
    		} else {
    		  	//如果不是以上三种类型,记录这次错误并退出
    			return $this->sanityFail("Could not match mime type after verifying it previously.");
    		}
    		//优先使用optipng工具进行png<strong><strong>图片</strong></strong>的压缩,前提是你装了这个工具
    		if($imgType == 'png' && OPTIPNG_ENABLED && OPTIPNG_PATH && @is_file(OPTIPNG_PATH)){
    		  	//记录optipng的地址
    		  	$exec = OPTIPNG_PATH;
    			//写日志,记录optipng将运行,级别3
    			$this->debug(3, "optipng'ing $tempfile");
    			//获取<strong><strong>图片</strong></strong>大小
    			$presize = filesize($tempfile);
    			//进行<strong><strong>图片</strong></strong>压缩操作
    			$out = `$exec -o1 $tempfile`;
    		       	//清除文件状态缓存	
    			clearstatcache();
    			//获取压缩后的文件大小
    			$aftersize = filesize($tempfile);
    			//算出压缩了多大
    			$sizeDrop = $presize - $aftersize;
    			//根据算出的不同的值,写日志,级别1
    			if($sizeDrop > 0){
    				$this->debug(1, "optipng reduced size by $sizeDrop");
    			} else if($sizeDrop < 0){
    				$this->debug(1, "optipng increased size! Difference was: $sizeDrop");
    			} else {
    				$this->debug(1, "optipng did not change image size.");
    			}
    		//optipng不存在,就尝试使用pngcrush
    		} else if($imgType == 'png' && PNGCRUSH_ENABLED && PNGCRUSH_PATH && @is_file(PNGCRUSH_PATH)){
    		  	$exec = PNGCRUSH_PATH;
    			//和optipng不同的是,pngcrush会将<strong>处理</strong>完的文件新生成一个文件,所以这里新建个文件
    			$tempfile2 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
    			//写日志,记录文件名
    			$this->debug(3, "pngcrush'ing $tempfile to $tempfile2");
    			//运行pngcrush
    			$out = `$exec $tempfile $tempfile2`;
    			$todel = "";
    			//如果生成文件成功
    			if(is_file($tempfile2)){
    			  	//算出压缩后的文件大小的差值
    			  	$sizeDrop = filesize($tempfile) - filesize($tempfile2);
    				//如果是一次有效的压缩,则将压缩后的文件作为缓存文件
    				if($sizeDrop > 0){
    					$this->debug(1, "pngcrush was succesful and gave a $sizeDrop byte size reduction");
    					$todel = $tempfile;
    					$tempfile = $tempfile2;
    				//否则的话则这个文件没有存在的必要
    				} else {
    					$this->debug(1, "pngcrush did not reduce file size. Difference was $sizeDrop bytes.");
    					$todel = $tempfile2;
    				}
    			//没有运行成功也需要删除这个文件
    			} else {
    				$this->debug(3, "pngcrush failed with output: $out");
    				$todel = $tempfile2;
    			}
    			//删除无效文件或压缩前比较大的文件
    			@unlink($todel);
    		}
    		//在缓存<strong><strong>图片</strong></strong>上写入安全头
    		$this->debug(3, "Rewriting image with security header.");
    		//创建一个新的缓存文件
    		$tempfile4 = tempnam($this->cacheDirectory, 'timthumb_tmpimg_');
    		//
    		$context = stream_context_create ();
    		//读取生成的<strong><strong>图片</strong></strong>缓存内容
    		$fp = fopen($tempfile,'r',0,$context);
    		//向新缓存文件写入安全头,安全头的长度应该总是$this->filePrependSecurityBlock的长度 + 6
    		file_put_contents($tempfile4, $this->filePrependSecurityBlock . $imgType . ' ?' . '>');
    		//将读取出来的缓存<strong><strong>图片</strong></strong>内容写入新缓存文件
    		file_put_contents($tempfile4, $fp, FILE_APPEND);
    		//关闭文件资源
    		fclose($fp);
    		//删除之前不安全的<strong><strong>图片</strong></strong>缓存文件
    		@unlink($tempfile);
    		//写日志,给缓存文件加锁~~
    		$this->debug(3, "Locking and replacing cache file.");
    		//创建锁文件文件名
    		$lockFile = $this->cachefile . '.lock';
    		//创建或打开锁文件
    		$fh = fopen($lockFile, 'w');
    		//创建失败直接退出
    		if(! $fh){
    			return $this->error("Could not open the lockfile for writing an image.");
    		}
    		//如果给锁文件加入写入锁成功
    		if(flock($fh, LOCK_EX)){
    		  	//删除原缓存文件
    		  	@unlink($this->cachefile); 
    			//重命名覆盖,将安全的缓存文件作为缓存文件
    			rename($tempfile4, $this->cachefile);
    			//释放写入锁
    			flock($fh, LOCK_UN);
    			//释放资源
    			fclose($fh);
    			//删除锁文件
    			@unlink($lockFile);
    		//否则
    		} else {
    		  	//关闭资源
    		  	fclose($fh);
    			//删除锁文件
    			@unlink($lockFile);
    			//删除安全的缓存文件
    			@unlink($tempfile4);
    			//记录错误并退出
    			return $this->error("Could not get a lock for writing.");
    		}
    		//写日志,记录操作完成
    		$this->debug(3, "Done image replace with security header. Cleaning up and running cleanCache()");
    		//释放<strong><strong>图片</strong></strong>资源
    		imagedestroy($canvas);
    		imagedestroy($image);
    		//生成缓存成功返回真
    		return true;
    	}
    	/*此函数用来获取服务器文档根目录*/
    	protected function calcDocRoot(){
    	  	//直接获取文档根目录
    	  	$docRoot = @$_SERVER['DOCUMENT_ROOT'];
    		//如果定义了LOCAL_FILE_BASE_DIRECTORY,则使用此值
    		if (defined('LOCAL_FILE_BASE_DIRECTORY')) {
    			$docRoot = LOCAL_FILE_BASE_DIRECTORY;   
    		}
    		//如果没有获取到文档根目录,也就是DOCUMENT_ROOT的值
    		if(!isset($docRoot)){
    		  	//写一条记录,说明DOCUMENT_ROOT没找到,注意level是3
    		  	$this->debug(3, "DOCUMENT_ROOT is not set. This is probably windows. Starting search 1.");
    			//用SCRIPT_FILENAME和PHP_SELF来得到文档根目录
    			if(isset($_SERVER['SCRIPT_FILENAME'])){
    			  	$docRoot = str_replace( '\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0-strlen($_SERVER['PHP_SELF'])));
    				//写一条记录,说明DOCUMENT_ROOT的值是通过SCRIPT_FILENAME和PHP_SELF来得的,级别3
    				$this->debug(3, "Generated docRoot using SCRIPT_FILENAME and PHP_SELF as: $docRoot");
    			} 
    		}
    		//如果还是没有获取到文档根目录
    		if(!isset($docRoot)){
    		  	//先写一条记录,说明还是没得到DOCUMENT_ROOT,级别3
    		  	$this->debug(3, "DOCUMENT_ROOT still is not set. Starting search 2.");
    			//通过PATH_TRANSLATED和PHP_SELF来得到文档根目录,关于PATH_TRANSLATED的说明可以看这里:http://blogs.msdn.com/b/david.wang/archive/2005/08/04/what-is-path-translated.aspx
    			if(isset($_SERVER['PATH_TRANSLATED'])){
    			  	$docRoot = str_replace( '\', '/', substr(str_replace('\\', '\', $_SERVER['PATH_TRANSLATED']), 0, 0-strlen($_SERVER['PHP_SELF'])));
    				//写记录,说明说明DOCUMENT_ROOT的值是通过PATH_TRANSLATED和PHP_SELF来得的,级别3
    				$this->debug(3, "Generated docRoot using PATH_TRANSLATED and PHP_SELF as: $docRoot");
    			} 
    		}
    		//如果文档根目录不是服务器根目录,则去掉最后一个 '/'
    		if($docRoot && $_SERVER['DOCUMENT_ROOT'] != '/'){ $docRoot = preg_replace('//$/', '', $docRoot); }
    		//写记录,说明文档根目录的值,级别3
    		$this->debug(3, "Doc root is: " . $docRoot);
    		//赋值给成员属性
    		$this->docRoot = $docRoot;
    	}
    	/*此函数用来获取本地<strong><strong>图片</strong></strong>地址,参数src是相对与文档根目录的地址*/
    	protected function getLocalImagePath($src){
    	  	//去掉开头的 / 
    	 	 $src = ltrim($src, '/');
    		 //如果前面没有获取到文档根目录,出于安全考虑,那么这里只能对timthumbs.php所在的目录下的<strong><strong>图片</strong></strong>进行操作
    		 if(! $this->docRoot){
    		   	//写日志,级别3,说明下面进行<strong><strong>图片</strong></strong>地址的检查
    			$this->debug(3, "We have no document root set, so as a last resort, lets check if the image is in the current dir and serve that.");
    			//获取去掉所有路径信息的文件名
    			$file = preg_replace('/^.*?([^/\\]+)$/', '$1', $src); 
    			//如果<strong><strong>图片</strong></strong>文件和timthumb.php在同一目录下
    			if(is_file($file)){
    			  	//返回此<strong><strong>图片</strong></strong>的路径
    				return $this->realpath($file);
    			}
    			//如果<strong><strong>图片</strong></strong>文件和timthumb.php不在同一目录下,写错误信息,出于安全考虑,不会允许一个没有文档根目录并且在timthumbs.php所在的目录以外的文件
    			return $this->error("Could not find your website document root and the file specified doesn't exist in timthumbs directory. We don't support serving files outside timthumb's directory without a document root for security reasons.");
    		}
    		 //尝试找这张<strong><strong>图片</strong></strong>,如果<strong><strong>图片</strong></strong>地址存在
    		 if(file_exists ($this->docRoot . '/' . $src)) {
    		   	//写日志,记录文件地址,级别3
    		   	$this->debug(3, "Found file as " . $this->docRoot . '/' . $src);
    			//返回<strong><strong>图片</strong></strong>路径
    			$real = $this->realpath($this->docRoot . '/' . $src);
    			//验证<strong><strong>图片</strong></strong>路径是否在本机
    			if(stripos($real, $this->docRoot) === 0){
    			  	//是的话返回<strong><strong>图片</strong></strong>地址
    				return $real;
    			} else {
    			  	//否则写日志,没找到指定文件,级别1
    				$this->debug(1, "Security block: The file specified occurs outside the document root.");
    			}
    		}
    		//接着找。。。
    		 $absolute = $this->realpath('/' . $src);
    		 //如果决定地址存在
    		 if($absolute && file_exists($absolute)){
    		  	//写日志,记录<strong><strong>图片</strong></strong>绝对地址,级别3 
    		   	$this->debug(3, "Found absolute path: $absolute");
    			//如果文档根目录没有定义,记录这个错误信息
    			if(! $this->docRoot){ $this->sanityFail("docRoot not set when checking absolute path."); }
    			//验证<strong><strong>图片</strong></strong>路径是否在本机
    			if(stripos($absolute, $this->docRoot) === 0){
    				//在的话返回<strong><strong>图片</strong></strong>地址    
    				return $absolute;
    			} else {
    			  	//否则写日志,没找到指定的文件,级别1
    				$this->debug(1, "Security block: The file specified occurs outside the document root.");
    			}
    		}
    		//如果还没找到指定文件,则逐级向上查找
    		$base = $this->docRoot;
    		
    		// 获取查询子目录列表
    		if (strstr($_SERVER['SCRIPT_FILENAME'],':')) {
    			$sub_directories = explode('\', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
    		} else {
    			$sub_directories = explode('/', str_replace($this->docRoot, '', $_SERVER['SCRIPT_FILENAME']));
    		}
    		//遍历子目录数组
    		foreach ($sub_directories as $sub){
    		  	//重新组合请求地址
    		  	$base .= $sub . '/';
    			//写日志,记录搜索记录,级别3
    			$this->debug(3, "Trying file as: " . $base . $src);
    			//如果找到了这个文件
    			if(file_exists($base . $src)){
    			  	//写日志,记录文件地址,级别3
    			  	$this->debug(3, "Found file as: " . $base . $src);
    				//得到实际地址
    				$real = $this->realpath($base . $src);
    				//如果实际地址的确在本机中,那么返回这个地址
    				if(stripos($real, $this->realpath($this->docRoot)) === 0){
    					return $real;
    				} else {
    				  	//找不到就写日志,没找到,级别1
    					$this->debug(1, "Security block: The file specified occurs outside the document root.");
    				}
    			}
    		}
    		//还找不到的话,就返回false;
    		return false;
    	}
    	/*此函数用来获得传入文件参数的真实路径*/
    	protected function realpath($path){
    		//去除路径中带有..的相对路径
    		$remove_relatives = '/w+/..//';
    		while(preg_match($remove_relatives,$path)){
    		    $path = preg_replace($remove_relatives, '', $path);
    		}
    		//如果去除后路径中仍有..的相对路径,则用realpath函数返回路径,否则直接返回即可
    		return preg_match('#^../|/../#', $path) ? realpath($path) : $path;
    	}
    	/*此函数用来记录在析构函数中需要删除的资源列表*/
    	protected function toDelete($name){
    	  	//写日志,记录需要删除的文件信息
    	  	$this->debug(3, "Scheduling file $name to delete on destruct.");
    		//添加到待删除数组
    		$this->toDeletes[] = $name;
    	}
    	/*此函数是截图操作的具体实现*/
    	protected function serveWebshot(){
    	  	//写日志,记录开始截图操作,级别3
    	  	$this->debug(3, "Starting serveWebshot");
    		//一段提示文字,可以到http://code.google.com/p/timthumb/上按照教程进行网站截图设置
    		$instr = "Please follow the instructions at http://code.google.com/p/timthumb/ to set your server up for taking website screenshots.";
    		//如果CutyCapt不存在
    		if(! is_file(WEBSHOT_CUTYCAPT)){
    		  	//退出执行并记录,CutyCapt未被安装
    			return $this->error("CutyCapt is not installed. $instr");
    		}
    		//如果xvfb不存在
    		if(! is_file(WEBSHOT_XVFB)){
    		  	//退出执行并记录,xvfb未被安装
    			return $this->Error("Xvfb is not installed. $instr");
    		}
    		//CUTYCAPT地址
    		$cuty = WEBSHOT_CUTYCAPT;
    		//xvfb地址
    		$xv = WEBSHOT_XVFB;
    		//截图屏幕宽度
    		$screenX = WEBSHOT_SCREEN_X;
    		//截图屏幕高度
    		$screenY = WEBSHOT_SCREEN_Y;
    		//截图色深
    		$colDepth = WEBSHOT_COLOR_DEPTH;
    		//截图保存格式
    		$format = WEBSHOT_IMAGE_FORMAT;
    		//截图超时时间,单位ms
    		$timeout = WEBSHOT_TIMEOUT * 1000;
    		//USER_AGENT头
    		$ua = WEBSHOT_USER_AGENT;
    		//是否启用js
    		$jsOn = WEBSHOT_JAVASCRIPT_ON ? 'on' : 'off';
    		//是否启用java
    		$javaOn = WEBSHOT_JAVA_ON ? 'on' : 'off';
    		//是否启用其他插件
    		$pluginsOn = WEBSHOT_PLUGINS_ON ? 'on' : 'off';
    		//是否启用代理
    		$proxy = WEBSHOT_PROXY ? ' --http-proxy=' . WEBSHOT_PROXY : '';
    		//在缓存文件目录,建立一个具有唯一文件名的文件,文件名前缀为timthumb_webshot,用户存储截图后的<strong><strong>图片</strong></strong>
    		$tempfile = tempnam($this->cacheDirectory, 'timthumb_webshot');
    		//目标网站地址
    		$url = $this->src;
    		//验证url合法性
    		if(! preg_match('/^https?://[a-zA-Z0-9.-]+/i', $url)){
    		  	//不合法退出执行
    			return $this->error("Invalid URL supplied.");
    		}
    		//过滤掉非法字符
    		$url = preg_replace('/[^A-Za-z0-9-._~:/?#[]@!$&'()*+,;=]+/', '', $url);
    		//优先使用CUTYCAPT
    		if(WEBSHOT_XVFB_RUNNING){
    		  	//设置系统变量,配置图形输出显示。
    		  	putenv('DISPLAY=:100.0');
    			//组装shell命令
    			$command = "$cuty $proxy --max-wait=$timeout --user-agent="$ua" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url="$url" --out-format=$format --out=$tempfile";
    		//否则使用XVFB
    		} else {
    			$command = "$xv --server-args="-screen 0, {$screenX}x{$screenY}x{$colDepth}" $cuty $proxy --max-wait=$timeout --user-agent="$ua" --javascript=$jsOn --java=$javaOn --plugins=$pluginsOn --js-can-open-windows=off --url="$url" --out-format=$format --out=$tempfile";
    		}
    		//写日志,记录执行的命令,级别3
    		$this->debug(3, "Executing command: $command");
    		//执行命令并捕获输出
    		$out = `$command`;
    		//写日志,记录输出,级别3
    		$this->debug(3, "Received output: $out");
    		//如果刚刚创建的唯一文件名的文件失败
    		if(! is_file($tempfile)){
    		  	//设置404错误
    		  	$this->set404();
    		  	//推出脚本
    			return $this->error("The command to create a thumbnail failed.");
    		}
    		//启用裁剪
    		$this->cropTop = true;
    		//对截取到的<strong><strong>图片</strong></strong>文件<strong>处理</strong>并生成缓存
    		if($this->processImageAndWriteToCache($tempfile)){
    		  	//成功的话写日志,并从缓存读取此<strong><strong>图片</strong></strong>
    		  	$this->debug(3, "Image processed succesfully. Serving from cache");
    			//返回从缓存中读取的文件内容
    			return $this->serveCacheFile();
    		//没成功就返回假咯
    		} else {
    			return false;
    		}
    	}
    	/*此函数用来从外部url获取图像*/
    	protected function serveExternalImage(){
    	  	//验证url合法性
    		if(! preg_match('/^https?://[a-zA-Z0-9-.]+/i', $this->src)){
    			$this->error("Invalid URL supplied.");
    			return false;
    		}
    		//生成临时缓存文件
    		$tempfile = tempnam($this->cacheDirectory, 'timthumb');
    		//写日志,记录读取外部图像到临时文件,级别3
    		$this->debug(3, "Fetching external image into temporary file $tempfile");
    		//将临时缓存文件加入到待删除列表
    		$this->toDelete($tempfile);
    		//请求url并将结果写入到临时缓存文件中,如果没有成功
    		if(! $this->getURL($this->src, $tempfile)){
    		  	//删除此缓存文件
    		  	@unlink($this->cachefile);
    			//再创建一个新的缓存文件
    			touch($this->cachefile);
    			//写日志,记录错误信息,级别3
    			$this->debug(3, "Error fetching URL: " . $this->lastURLError);
    			//写错误信息,并退出
    			$this->error("Error reading the URL you specified from remote host." . $this->lastURLError);
    			return false;
    		}
    		//得到获取到<strong><strong>图片</strong></strong>的MIME类型
    		$mimeType = $this->getMimeType($tempfile);
    		//如果不在这三种类型中
    		if(! preg_match("/^image/(?:jpg|jpeg|gif|png)$/i", $mimeType)){
    		  	//写日志,记录错误信息,级别3
    		  	$this->debug(3, "Remote file has invalid mime type: $mimeType");
    			//删除现有缓存文件
    			@unlink($this->cachefile);
    			//创建新缓存文件
    			touch($this->cachefile);
    			//写错误信息并退出
    			$this->error("The remote file is not a valid image.");
    			return false;
    		}
    		//<strong>处理</strong>图像并缓存
    		if($this->processImageAndWriteToCache($tempfile)){
    		  	$this->debug(3, "Image processed succesfully. Serving from cache");
    		  	//成功的话返回缓存信息
    			return $this->serveCacheFile();
    		} else {
    		  	//失败返回假
    			return false;
    		}
    	}
    	/*此函数用来将curl获取到的数据写入对应文件中*/
    	public static function curlWrite($h, $d){
    	  	//将数据写入文件
    	  	fwrite(self::$curlFH, $d);
    		//记录数据长度
    		self::$curlDataWritten += strlen($d);
    		//如果<strong><strong>图片</strong></strong>大小超过了配置文件的限制,则返回0
    		if(self::$curlDataWritten > MAX_FILE_SIZE){
    		  	return 0;
    		//否则返回<strong><strong>图片</strong></strong>大小
    		} else {
    			return strlen($d);
    		}
    	}
    	/*此函数用来读取并输出服务端缓存*/
    	protected function serveCacheFile(){
    	  	//写日志,记录读取缓存的地址
    	  	$this->debug(3, "Serving {$this->cachefile}");
    		//如果缓存地址无效
    		if(! is_file($this->cachefile)){
    		  	//添加到错误记录
    		  	$this->error("serveCacheFile called in timthumb but we couldn't find the cached file.");
    			//停止执行脚本
    			return false;
    		}
    		//缓存地址有效的话,已只读方式打开文件
    		$fp = fopen($this->cachefile, 'rb');
    		//如果打开失败,直接退出脚本,并记录错误信息
    		if(! $fp){ return $this->error("Could not open cachefile."); }
    		//设定文件指针跳过filePrependSecurityBlock值,也就是跳过安全头后开始读
    		fseek($fp, strlen($this->filePrependSecurityBlock), SEEK_SET);
    		//读出文件的mime类型
    		$imgType = fread($fp, 3);
    		//再跳过这个mime类型的值
    		fseek($fp, 3, SEEK_CUR);
    		//如果现在文件的指针不是在安全头后6个字符的位置,说明缓存文件可能已损坏
    		if(ftell($fp) != strlen($this->filePrependSecurityBlock) + 6){
    		  	//删除此缓存文件
    		  	@unlink($this->cachefile);
    			//记录错误并退出执行
    			return $this->error("The cached image file seems to be corrupt.");
    		}
    		//缓存<strong><strong>图片</strong></strong>的实际大小应该是文件大小 - 安全头大小
    		$imageDataSize = filesize($this->cachefile) - (strlen($this->filePrependSecurityBlock) + 6);
    		//设置输出必要的HTTP头
    		$this->sendImageHeaders($imgType, $imageDataSize);
    		//输出文件指针处所有剩余数据
    		$bytesSent = @fpassthru($fp);
    		//关闭文件资源
    		fclose($fp);
    		//如果此方法执行成功,则返回真
    		if($bytesSent > 0){
    			return true;
    		}
    		//如果fpassthru不成功,则用file_get_contents读取并输出
    		$content = file_get_contents ($this->cachefile);
    		//如果读取成功
    		if ($content != FALSE) {
    		  	//截取掉安全头
    		  	$content = substr($content, strlen($this->filePrependSecurityBlock) + 6);
    			//输出图像
    			echo $content;
    			//写日志,记录读取缓存的方式
    			$this->debug(3, "Served using file_get_contents and echo");
    			return true;
    		//读取失败的话记录错误信息并退出执行
    		} else {
    			$this->error("Cache file could not be loaded.");
    			return false;
    		}
    	}
    	/*此函数设置<strong><strong>图片</strong></strong>输出必要的http头*/
    	protected function sendImageHeaders($mimeType, $dataSize){
    	  	//补全<strong><strong>图片</strong></strong>的mime信息
    		if(! preg_match('/^image//i', $mimeType)){
    			$mimeType = 'image/' . $mimeType;
    		}
    		//将jpg的mime类型写标准,这里不标准的原因是在验证文件安全头时追求了便利性
    		if(strtolower($mimeType) == 'image/jpg'){
    			$mimeType = 'image/jpeg';
    		}
    		//浏览器缓存失效时间
    		$gmdate_expires = gmdate ('D, d M Y H:i:s', strtotime ('now +10 days')) . ' GMT';
    		//文档最后被修改时间,用来让浏览器判断是否需要重新请求页面
    		$gmdate_modified = gmdate ('D, d M Y H:i:s') . ' GMT';
    		// 设置HTTP头
    		header ('Content-Type: ' . $mimeType);
    		header ('Accept-Ranges: none'); 
    		header ('Last-Modified: ' . $gmdate_modified);
    		header ('Content-Length: ' . $dataSize);
    		//如果配置文件禁止浏览器缓存,则设置相应的HTTP头信息
    		if(BROWSER_CACHE_DISABLE){
    			$this->debug(3, "Browser cache is disabled so setting non-caching headers.");
    			header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    			header("Pragma: no-cache");
    			header('Expires: ' . gmdate ('D, d M Y H:i:s', time()));
    		//否则按配置文件设置缓存时间
    		} else {
    			$this->debug(3, "Browser caching is enabled");
    			header('Cache-Control: max-age=' . BROWSER_CACHE_MAX_AGE . ', must-revalidate');
    			header('Expires: ' . $gmdate_expires);
    		}
    		//运行成功返回真
    		return true;
    	}
    	/*自定义的验证函数*/
    	protected function securityChecks(){
    	}
    	/*此函数用来获取$_GET数组中的参数,并允许设置默认值*/
    	protected function param($property, $default = ''){
    	  	//如果参数存在则返回此参数
    		if (isset ($_GET[$property])) {
    		  	return $_GET[$property];
    		//不存在的话返回默认值
    		} else {
    			return $default;
    		}
    	}
    	/*此函数根据传入mime类型,打开图像资源*/
    	protected function openImage($mimeType, $src){
    		switch ($mimeType) {
    			case 'image/jpeg':
    				$image = imagecreatefromjpeg ($src);
    				break;
    			case 'image/png':
    				$image = imagecreatefrompng ($src);
    				break;
    			case 'image/gif':
    				$image = imagecreatefromgif ($src);
    				break;
    			//不是这三种的话,脚本退出
    			default:
    				$this->error("Unrecognised mimeType");
    		}
    		//返回图像资源
    		return $image;
    	}
    	/*没啥说的,获取客户端IP*/
    	protected function getIP(){
    		$rem = @$_SERVER["REMOTE_ADDR"];
    		$ff = @$_SERVER["HTTP_X_FORWARDED_FOR"];
    		$ci = @$_SERVER["HTTP_CLIENT_IP"];
    		if(preg_match('/^(?:192.168|172.16|10.|127.)/', $rem)){ 
    			if($ff){ return $ff; }
    			if($ci){ return $ci; }
    			return $rem;
    		} else {
    			if($rem){ return $rem; }
    			if($ff){ return $ff; }
    			if($ci){ return $ci; }
    			return "UNKNOWN";
    		}
    	}
    	/*debug运行日志函数,用来向系统日志记录操作信息*/
    	protected function debug($level, $msg){
    	  	//如果开启了debug,并且$level也就是调试级别小于等于配置文件中的值,则开始记录
    	  	if(DEBUG_ON && $level <= DEBUG_LEVEL){
    			//格式化并记录开始时间,保留小数点后6位,这个时间代表实例化类后到这个debug执行所经历的时间
    		  	$execTime = sprintf('%.6f', microtime(true) - $this->startTime);
    			//这个值代表从上次debug结束,到这次debug的用时
    			$tick = sprintf('%.6f', 0);
    			//如果上次debug时间存在,则用当前时间减去上次debug时间,得出差值
    			if($this->lastBenchTime > 0){
    				$tick = sprintf('%.6f', microtime(true) - $this->lastBenchTime);
    			}
    			//将时间更新
    			$this->lastBenchTime = microtime(true);
    			//将debug信息写到系统日志中
    			error_log("TimThumb Debug line " . __LINE__ . " [$execTime : $tick]: $msg");
    		}
    	}
    	/*此函数用来记录未知BUG*/
    	protected function sanityFail($msg){
    	  	//记录BUG信息
    		return $this->error("There is a problem in the timthumb code. Message: Please report this error at <a href='http://code.google.com/p/timthumb/issues/list'>timthumb's bug tracking page</a>: $msg");
    	}
    	/*此函数用来返回<strong><strong>图片</strong></strong>文件的MIME信息*/
    	protected function getMimeType($file){
    	  	//获取<strong><strong>图片</strong></strong>文件的信息
    	  	$info = getimagesize($file);
    		//成功则返回MIME信息
    		if(is_array($info) && $info['mime']){
    			return $info['mime'];
    		}
    		//失败返回空
    		return '';
    	}
    	/*此函数用来检测并设置php运行时最大占用内存的值*/
    	protected function setMemoryLimit(){
    	  	//获取php.ini中的最大内存占用的值
    	  	$inimem = ini_get('memory_limit');
    		//将上面得到的值转换为以字节为单位的数值
    		$inibytes = timthumb::returnBytes($inimem);
    		//算出配置文件中内存限制的值
    		$ourbytes = timthumb::returnBytes(MEMORY_LIMIT);
    		//如果php配置文件中的值小于自己设定的值
    		if($inibytes < $ourbytes){
    		  	//则将php.ini配置中关于最大内存的值设置为自己设定的值
    		  	ini_set ('memory_limit', MEMORY_LIMIT);
    		  	//写日志,记录改变内存操作,级别3
    			$this->debug(3, "Increased memory from $inimem to " . MEMORY_LIMIT);
    		//如果自己设置的值小于php.ini中的值
    		} else {
    		  	//则不进行任何操作,写日志记录此条信息即可,级别3
    			$this->debug(3, "Not adjusting memory size because the current setting is " . $inimem . " and our size of " . MEMORY_LIMIT . " is smaller.");
    		}
    	}
    	/*此函数将G, KB, MB 转为B(字节)*/
    	protected static function returnBytes($size_str){
    	  	//取最后一个单位值,进行转换操作,并返回转换后的值
    		switch (substr ($size_str, -1))
    		{
    			case 'M': case 'm': return (int)$size_str * 1048576;
    			case 'K': case 'k': return (int)$size_str * 1024;
    			case 'G': case 'g': return (int)$size_str * 1073741824;
    			default: return $size_str;
    		}
    	}
    	/*此函数用来将url中的资源读取到tempfile文件中*/
    	protected function getURL($url, $tempfile){
    	  	//重置上次url请求错误信息
    	  	$this->lastURLError = false;
    	  	//进行url编码
    		$url = preg_replace('/ /', '%20', $url);
    		//优先使用curl扩展
    		if(function_exists('curl_init')){
    		  	//写日志,记录将使用curl扩展访问url,级别3
    		  	$this->debug(3, "Curl is installed so using it to fetch URL.");
    			//打开文件
    			self::$curlFH = fopen($tempfile, 'w');
    			//如果打开失败,记录错误信息并退出
    			if(! self::$curlFH){
    				$this->error("Could not open $tempfile for writing.");
    				return false;
    			}
    			//重置写入长度
    			self::$curlDataWritten = 0;
    			//写日志,记录访问的url信息,级别3
    			$this->debug(3, "Fetching url with curl: $url");
    			//初始化curl
    			$curl = curl_init($url);
    			//curl选项设置
    			curl_setopt ($curl, CURLOPT_TIMEOUT, CURL_TIMEOUT);
    			curl_setopt ($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30");
    			curl_setopt ($curl, CURLOPT_RETURNTRANSFER, TRUE);
    			curl_setopt ($curl, CURLOPT_HEADER, 0);
    			curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    			//关闭会话时执行curlWrite
    			curl_setopt ($curl, CURLOPT_WRITEFUNCTION, 'timthumb::curlWrite');
    			@curl_setopt ($curl, CURLOPT_FOLLOWLOCATION, true);
    			@curl_setopt ($curl, CURLOPT_MAXREDIRS, 10);
    			//执行本次请求,并将结果赋给$curlResult
    			$curlResult = curl_exec($curl);
    			//释放文件资源
    			fclose(self::$curlFH);
    			//获取最后一个受到的HTTP码
    			$httpStatus = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    			//如果是404,那么设置404错误并退出
    			if($httpStatus == 404){
    				$this->set404();
    			}
    			//如果请求成功
    			if($curlResult){
    			  	//关闭curl,并执行curlWrite将数据写到文件中
    			  	curl_close($curl);
    			  	//返回真,请求完成
    				return true;
    			//如果请求不成功
    			} else {
    			  	//记录错误信息
    			  	$this->lastURLError = curl_error($curl);
    				//关闭资源
    				curl_close($curl);
    				//执行不成功
    				return false;
    			}
    		//如果不支持curl,用file_get_contents获取数据
    		} else {
    		  	//获取数据
    		  	$img = @file_get_contents ($url);
    			//如果获取失败
    			if($img === false){
    			  	//记录返回的错误信息数组
    			  	$err = error_get_last();
    			  	//如果记录到了,并且有错误信息
    				if(is_array($err) && $err['message']){
    				  	//则记录这个错误信息
    				  	$this->lastURLError = $err['message'];
    				//否则的话记录整个错误信息
    				} else {
    					$this->lastURLError = $err;
    				}
    				//如果错误信息中有404,则设置为404错误
    				if(preg_match('/404/', $this->lastURLError)){
    					$this->set404();
    				}
    				//返回假
    				return false;
    			}
    			//如果将读取的<strong><strong>图片</strong></strong>写入文件失败
    			if(! file_put_contents($tempfile, $img)){
    			  	//写错误信息并退出执行
    				$this->error("Could not write to $tempfile.");
    				return false;
    			}
    			//没问题的话执行成功
    			return true;
    		}
    	}
    	/*此函数输出指定的<strong><strong>图片</strong></strong>,用于输出错误信息中*/
    	protected function serveImg($file){
    	  	//获取图像信息
    	  	$s = getimagesize($file);
    		//如果获取不到图像信息,推出
    		if(! ($s && $s['mime'])){
    			return false;
    		}
    		//设置http头,输出<strong><strong>图片</strong></strong>
    		header ('Content-Type: ' . $s['mime']);
    		header ('Content-Length: ' . filesize($file) );
    		header ('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
    		header ("Pragma: no-cache");
    		//使用readfile输出<strong><strong>图片</strong></strong>
    		$bytes = @readfile($file);
    		if($bytes > 0){
    			return true;
    		}
    		//如果失败,使用file_get_contents和echo输出<strong><strong>图片</strong></strong>
    		$content = @file_get_contents ($file);
    		if ($content != FALSE){
    			echo $content;
    			return true;
    		}
    		//还失败的话返回假
    		return false;
    	}
    	/*此函数设置404 错误码*/
    	protected function set404(){
    		$this->is404 = true;
    	}
    	/*此函数返回404错误码*/
    	protected function is404(){
    		return $this->is404;
    	}
    }

  • 配置docker desktop的境像下载地址为国内镜像地址

    配置docker desktop的境像下载地址为国内镜像地址

    右键右下角 docker的托盘图标,依次打开  Setings >> Docker Engine,在Docker Engine里配置如下内容,

    {
      "registry-mirrors": [
        "https://registry.docker-cn.com",
        "http://hub-mirror.c.163.com",
        "https://docker.mirrors.ustc.edu.cn"
      ],
      "insecure-registries": [],
      "debug": true,
      "experimental": false
    }

    然后点击右边的”Apply & Restart” 按钮保存与重新docker。

    Docker中国区官方镜像地址: https://registry.docker-cn.com

    网易地址: http://hub-mirror.c.163.com
    中国科技大学地址: https://docker.mirrors.ustc.edu.cn

  • Windows下wsl更新到wsl2适用于 Linux 的 Windows 子系统安装指南 (Windows 10)

    Windows下wsl更新到wsl2适用于 Linux 的 Windows 子系统安装指南 (Windows 10)

    刚好将本机的WSL升级到WSL2,下面给出官方的文档地址,适用于 Linux 的 Windows 子系统安装指南 (Windows 10)

    https://docs.microsoft.com/zh-cn/windows/wsl/install-win10

WeChat