Web服务移植thttpd在ARM移植_第1页
Web服务移植thttpd在ARM移植_第2页
Web服务移植thttpd在ARM移植_第3页
Web服务移植thttpd在ARM移植_第4页
Web服务移植thttpd在ARM移植_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、thttpd在ARM移植1 下载并解压:下载地址为: HYPERLINK /software/thttpd/ /software/thttpd/ 下载的是最新的2.25b解压: rootBinnary source# tar -xvzf thttpd-2.25b.tar.gz2 交叉编译thttpd rootBinnary source # cd thttpd-2.25brootBinnary thttpd-2.25b # CC=/armtools/bin/arm-linux-gcc ./configure -host=arm-linuxrootBinnary thttpd-2.25b # m

2、ake3 安装与配置3.1 拷贝thttpd二进制可执行文件到根文件系统/usr/sbin/目录中 rootBinnary thttpd-2.25b # cp thttpd /fs/usr/sbin/3.2 拷贝thttpd配置文件rootBinnary thttpd-2.25b # cp contrib/redhat-rpm/thttpd.conf /fs/etc/3.3在开发板上为thttpd创建一个独立的用户:httpd,并用此用户创建httpd服务的根目录html root/root#adduser httpd(在ARM开发板上去添加用户)Changing password for h

3、ttpdEnter the new password (minimum of 5, maximum of 8 characters)Please use a combination of upper and lower case letters and numbers.Enter new password:Bad password: too short.Warning: weak password (continuing).Re-enter new password:passwd786: password for httpd changed by user rootPassword chang

4、ed.root/root#exitprocess -/bin/login (pid 787) exited. Scheduling it for restart.starting pid 790, tty : /bin/login login: httpdPassword:Processing /etc/profile.Set search library path in /etc/profileSet user path in /etc/profileSet PS1 in /etc/profileDonehttpd/home/httpd #mkdir html 3.4 拷贝测试网页到http

5、d服务的根目(可选,测试之用): rootBinnary thttpd-2.25b # cp index.html /fs/home/httpd/html/我是动态编译所以查看一下需要的动态库 rootBinnary thttpd-2.25b # /armtools/bin/arm-linux-readelf -d thttpdDynamic section at offset 0 x12014 contains 21 entries:Tag Type Name/Value0 x00000001 (NEEDED) Shared library: libcrypt.so.10 x00000001

6、 (NEEDED) Shared library: libc.so.60 x0000000c (INIT) 0 x95480 x0000000d (FINI) 0 x165640 x00000004 (HASH) 0 x81280 x00000005 (STRTAB) 0 x8c140 x00000006 (SYMTAB) 0 x84940 x0000000a (STRSZ) 1066 (bytes)0 x0000000b (SYMENT) 16 (bytes)0 x00000015 (DEBUG) 0 x00 x00000003 (PLTGOT) 0 x220e40 x00000002 (P

7、LTRELSZ) 872 (bytes)0 x00000014 (PLTREL) REL0 x00000017 (JMPREL) 0 x91e00 x00000011 (REL) 0 x91a00 x00000012 (RELSZ) 64 (bytes)0 x00000013 (RELENT) 8 (bytes)0 x6ffffffe (VERNEED) 0 x91300 x6fffffff (VERNEEDNUM) 20 x6ffffff0 (VERSYM) 0 x903e0 x00000000 (NULL) 0 x0虽然这里只列出了需要libcrypt 和 libc 这两个动态库,但是想要

8、运行thttpd还需要libnss_files 动态库,具体原因如下解释: rootBinnary thttpd-2.25b$ cp -d /armtools/arm-linux/lib/libnss_files* /fs/lib/你可以在启动文件里增加thttpd的启动命令:thttpd -C /etc/thttpd.conf注意只有root有启动权限!4、增加对CGI的支持默认配置下,thttpd不可以运行GCI(特别是动态编译的CGI程序)要想使用CGI支持功能,必须更改thttpd.conf的配置:# This section overrides defaultsdir=/home/h

9、ttpd/html#chroot#屏蔽chroot是为了运行动态编译的CGIuser=httpd# default = nobodylogfile=/var/log/thttpd.logpidfile=/var/run/thttpd.pid# This section _documents_ defaults in effectport=80port参数用于更改端口号(可不改,若还运行了别的WEB服务器,则需用不同端口)# nosymlink# default = !chroot#symlinks# novhostcgipat=/cgi-bin/*声明CGI程序的目录,是以dir为根目录的路径

10、# nothrottles# host=# charset=iso-8859-1移植完成,可以测试了(只需在WEB浏览器中键入开发板的IP地址即可)。在建立 embedded Linux 系统 (root filesystem) 时,链接库相依 (library dependencies)是相当重要的目。当 root filesystem 缺少必要的 library 时,程序当然是无法执行的,甚致系统也会无法顺利启动。在建构 embedded Linux 系统时,应具备的正确观念与基本能力。我们把如何找出所需的 library方法整理出 3 项的基本要点,依照这 3 种基本款来加入 libra

11、ry 将能解决几乎所有的 library dependency 问题,这 3 种项基本要点为:(1) 先利用 cross toolchain 的 objdump 观察NEEDED的项目,加入 library。(2) 再检查这些 library 是否相依其它 library。(3) 最后要检视应用程序是否使用到需要特定 library 的service。要点 1. 跟 2. 对大家来说没有什么问题,要点 3. 在我们的 training 课程里,我们以建构 thttpd (embedded Web server) 的实际案例来做讲解。关于建构 thttpd 的案例thttpd 使用到 NSS (

12、Name Service Switch),因此若没有将 libnss_SERVICE.so 加到 root filesystem,thttpd 在执行时可能会遇到一些奇怪的问题。举个例子,当 thttpd 透过 /etc/passwd 去寻找 (查询) UNIX user 时,会用到 libnss_files.so (不读 /etc/shadow),因此会看到以下的错误讯息:unknown user - root出现这个错误的原因是 thttpd 读不到 root 使用者,要深入探讨这个问题的原理,必须从以下的程序代码片断开始探讨: 403 /* If were root and were g

13、oing to become another user, get the uid /gid 404 * now. 405 */ 406 if ( getuid() = 0 ) 407 408 pwd = getpwnam( user ); 409 if ( pwd = (struct passwd*) 0 ) 410 411 syslog( LOG_CRIT, unknown user - %.80s, user ); 412 (void) fprintf( stderr, %s: unknown user - %sn, argv0, user ); 413 exit( 1 ); 414 41

14、5 uid = pwd-pw_uid; 416 gid = pwd-pw_gid; 417 这段程序代码是 thttpd 2.25b 的程序片断,位于 thttpd.c 的 main() 函数里。关于 libnss_SERVICE.so 的议题,Jollen 打算另外再做讨论,因为还会与 libc 有关系。在这里我们由系统建构的角度来看这个问题。因为我们已经习惯用 objdump 来观察程序的相依 library,所以当 objdump 的画面跟我们预期的不同时,经常一时无法反应过来。例如,以下的讯息是我们所预期的:# /armtools/bin/arm-linux-objdump -x th

15、ttpd|more.Dynamic Section: NEEDED libcrypt.so.1 NEEDED libnss_files.so.2 NEEDED libc.so.6.但是实际的讯息却是像这样的:#/armtools/bin/arm-linux-objdump -x thttpd|more.Dynamic Section: NEEDED libcrypt.so.1 NEEDED libc.so.6.我们可以用一知半解的思考逻辑来解决问题:thttpd 呼叫到 getpwnam() 函数,此函数由 libnss_compat 提供,因此解决方案是把 libnss_files.so 加

16、到 root filesystem 里即可。且慢!前面才讲到 libnss_compat,怎么后面是把 libnss_files 加到 root filesystem?是这样的,libnss_compat 用来读 /etc/shadow,但是现在我们只需要由 /etc/passwd 读 Unix user,所以使用 libnss_files.so 就行了。执行 thttpd 的话,再加上指定 username 的参数来执行:# thttpd -p 80 -d /var/www -u rootlibnss_SERVICE.so 是包含在 glibc 里的链接库,因此可以直接由 cross too

17、lchain 里取得,不必再另行建置。有关 NSS (Name Service Switch) 可参考以下网页: HYPERLINK /software/libc/manual/html_node/Name-Service-Switch.html /software/libc/manual/html_node/Name-Service-Switch.html HYPERLINK /pub/gnu/Manuals/glibc-2.2.3/html_chapter/libc_28.html /pub/gnu/Manuals/glibc-2.2.3/html_chapter/libc_28.html

18、此处我们以service的角度来探讨这个问题:因为 thttpd 使用到 Name Service Switch,所以需要加入 libnss_SERVICE.so。另外一种探讨的角度是:由 programming 的角度来思考。如果要读 shadow passwd 的话,是使用 libnss_compat.so。Boa程序的移植1、下载Boa源码 下载地址: HYPERLINK / / 目前最新发行版本: 0.94.13 (几年没更新版本了) 下载 boa-0.94.13.tar.gz,注意:若从boa上下载的是boa-0.94.13.tar.tar,解压方式一样 解压: rootBinnar

19、y source# tar xzf boa-0.94.13.tar.gz2、生成Makefile文件进入boa-0.94.13,直接运行src/configure文件 rootBinnary src#CC=/armtools/bin/arm-linux-gcc ./configure#3、修改Makefile文件(注意:必须用cross-2.95.3, 如使用3.4.1、4.1.1等等会出错) #CC = /armtools/bin/arm-linux-gcc #CPP = /armtools/bin/arm-linux-gcc -E4、交叉编译 rootBinnary src# make5、

20、去除调试信息,减小体积。(可选) rootBinnary src# /armtools/bin/arm-linux-strip boa6、将编译好的程序放入根文件系统的/bin目录下。 rootBinnary src# cp boa /fs/bin/ 二、配置BoaBoa需要在/etc目录下建立一个boa目录,里面放入Boa的主要配置文件boa.conf。在Boa源码目录下已有一个示例boa.conf,可以在其基础上进行修改。 rootBinnary src# cd ./.rootBinnary source# cd ./fs/etc/rootBinnary etc# mkdir boaroo

21、tBinnary etc# chmod 777 boa/rootBinnary etc# cd boarootBinnary boa# kwrite boa.conf1、Group的修改修改 Group nogroup为 Group user(开发板上有的组)修改 User nobody为 User boa (user组中的一个成员)根据你的开发板的情况设定。一定要存在的组和用户。以下是我在开发板上的操作:rootlocalhost s#adduser -g user boaChanging password for boaEnter the new password (minimum of

22、5, maximum of 8 characters)Please use a combination of upper and lower case letters and numbers.Enter new password:Bad password: too short.Warning: weak password (continuing).Re-enter new password:passwd820: password for boa changed by user rootPassword changed.root#2、ScriptAlias的修改修改 ScriptAlias /c

23、gi-bin/ /usr/lib/cgi-bin/为 ScriptAlias /cgi-bin/ /var/www/cgi-bin/这是在设置CGI的目录,你也可以设置成别的目录。比如用户文件夹下的某个目录。3、ServerName的设置修改 #ServerName HYPERLINK .here/ .here为 ServerName HYPERLINK .here/ .here注意:该项默认为未打开,执行Boa会异常退出,提示“gethostbyname:No such file or directory”,所以必须打开。其它默认设置即可。你也可以设置为你自己想要的名字。比如我设置为:Ser

24、verName binnary2410此外,还需要:将mime.types文件复制/etc目录下,通常可以从linux主机的 /etc目录下直接复制即可。(以下配置和boa.conf的配置有关)创建日志文件所在目录/var/log/boa创建HTML文档的主目录/var/www创建CGI脚本所在录 /var/www/cgi-binrootBinnary log# mkdir -m 777 boarootBinnary log# cd .rootBinnary var# mkdir -m 777 wwwrootBinnary var# mkdir -m 777 www/cgi-binrootBi

25、nnary var# cd .rootBinnary rootfs# cp /etc/mime.types etc/三、运行Boa开发板操作:root#boa如果发现boa没有运行,则可以在开发板的/var/log/boa/error_log文件中找原因。比如端口已被其他程序占用: root#cat /var/log/boa/error_log20/Feb/2008:21:21:57 +0000 boa.c:194 - unable to bind: Address already in use或是用户设置错误等等,都可以查到。四、功能测试静态网页测试将静态网页存入根文件系统的/var/www

26、目录下(可以将主机 /usr/share/doc/HTML/目录下的index.html、homepage.css和img、stylesheet-images目录复制到/var/www目录下)在根文件系统的/var目录下 rootBinnary var# cp /usr/share/doc/HTML/index.html www/rootBinnary var# cp -r /usr/share/doc/HTML/img www/rootBinnary var# cp /usr/share/doc/HTML/homepage.css www/rootBinnary var# cp -r /us

27、r/share/doc/HTML/stylesheet-images www/直接在浏览器中输入开发板的IP地址(比如我的是 HYPERLINK 40) ,出现linux的欢迎网页。静态HTML调试成功。CGI功能测试1、编写HelloworldCGI.c程序rootBinnary source$ vi helloworldCGI.c(主程序的程序开头一定要用Tab,而不是空格,不然编译可能不通过)#include#includeint main(void)printf(Content-type: text/htmlnn);printf(n);printf(CGI Outputn);print

28、f(n);printf(Hello,world.n);printf(n);printf(n);exit(0);2.交叉编译生成CGI程序 rootBinnary source$ /armtools/bin/arm-linux-gcc -o helloworldCGI helloworldCGI.c将helloworldCGI 拷贝至根文件系统的/var/www/cgi-bin/下rootBinnary source$ cp helloworldCGI ./nfs/rootfs/var/www/cgi-bin/3.测试浏览器输入 HYPERLINK 40/cgi-bin/helloworldCG

29、I 40/cgi-bin/helloworldCGI 网页出现 Hello,world. 调试成功!附录资料:从 XML 生成可与 Ajax 共同使用的 JSON时下,非常流行使用 JavaScript 代码为数据驱动的 Web 应用程序添加互动性。若能将数据编码成 JavaScript Object Notation(JSON)的格式,您就可以更轻松地通过 JavaScript 语言使用它。通过本文,发掘使用 XSLT V2 从 XML 数据生成 JSON 的几种不同方法。几年前,许多开发人员很看好 XML、XSLT、Extensible HTML (XHTML)和其他一些基于标记的语言。现

30、在,Asynchronous JavaScript and XML(AJAX)成了新的热点,人们又将目光转向了使用 JavaScript 代码的数据驱动的富 Internet 应用程序。但是开发人员是否已经消除了 XML 和这一新技术之间的鸿沟呢?当然,您可以在 Web 客户机中使用 XML 解析器来读取数据,但这种做法会带来两个问题。第一,出于安全方面的原因,XML 数据只能从与此页面相同的那个域中读取。这虽然不是什么大的限制因素,但它的确会引起部署方面的问题,还会阻碍 DHTML 小部件的创建。第二,读取和解析 XML 会非常慢。另一种做法是让服务器执行 XML 的解析工作,方法是设置服务

31、器,使之向浏览器发送以 JavaScript 代码或时下流行的 JavaScript Object Notation(JSON)编码的数据。本文将展示如下三种使用 XSLT V2 语言和 Saxon XSLT V2 处理器从 XML 数据生成 JSON 的技巧: 简单编码 通过函数调用加载数据 编码对象 JSON 简介要学习如何将数据编码成 JSON(它只是 JavaScript 的一个子集),最好的方法是从数据开始。清单 1 显示了书籍列表的一个示例 XML 数据集。清单 1. 基本的图形化图书馆 Code Generation in Action JackHerrington Mannin

32、g PHP Hacks JackHerrington OReilly Podcasting Hacks JackHerrington OReilly 这个数据集很简单,只包含三本书,每本书都具有惟一的 ID、书名、作者姓名及出版商的名字。(没错,我只选择了我自己的书作为数据集,但能怨我吗?这些书实在是不可多得的节日和生日礼物。)清单 2 显示了这些数据在 JSON 中的效果。清单 2. JSON 中的示例数据集 id: 1, title: Code Generation in Action, first: Jack, last: Herrington, publisher: Manning ,

33、 . 方括号 () 表明这是一个数组。大括号 () 则表明这是一个散列表,该散列表由一组名称和值对组成。在本例中,我创建了一个散列表的数组 用来存储这类结构式数据的一种常见方法。另外一点值得注意的是字符串是通过单引号或双引号被编码的。所以,如果我想用单引号编码 OReilly,我就必须使用反斜杠对它进行转义:OReilly。 这让我编写的这个 XSLT 样式表更为有趣了一些。我并未在本例中放上任何日期,但您也可以通过如下两种方法来编码日期。第一种方法是将日期作为字符串,该字符串必须在后面被解析。第二种方法是将日期作为一个对象,比如:publishdate: new Date( 2006, 6,

34、 16, 17, 45, 0 )这段代码将 publishdate 的值设置为6/16/2006 5:45:00 p.m.。简单编码接下来我将陆续介绍 JSON 编码的几种技巧。第一种也是其中最简单的一种,此样式表如 清单 3 所示。清单 3. simple.xsl 样式表 var g_books = 1, id: ,name: ,first: ,last: ,publisher: ;要理解此样式表,不妨先来看一下 清单 4 所示的输出。清单 4. simple.xsl 的输出var g_books = id: 1,name: Code Generation in Action,first:

35、Jack,last: Herrington,publisher: Manning, id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly, id: 3,name: Podcasting Hacks,first: Jack,last: Herrington,publisher: OReilly;这里,我将名为 g_books 的变量设置为一个包含三个散列表的数组,每个散列表包含关于该书的信息。再回过头来看看 清单 3,您会发现第一个模板匹配 / 路径,它也是首先应用到输入数据集的模板,该模板使用 for-eac

36、h 循环来遍历每本书。之后,它使用 标记来将文本从该数据输出到 JavaScript 输出代码。对于字符串,我使用名为 js:escape() 的定制函数,它在模板之前定义。该函数使用一个正则表达式将一个单引号标记更改为带有反斜杠的单引号标记。最后一个重要的元素是 标记,它告知处理器要输出的是文本而不是 XML。要检验此过程是否可以正常工作,我加入了一个 simple .html 文件,该文件引用我在 simple.js 保存的 XSL 样式表的输出。这个 HTML 文件如 清单 5 所示。清单 5. simple.html 文件Simple JS loaderdocument.write(

37、Found +g_books.length+ books );.html 文件使用 标记简单地加载已编码了的 JavaScript 代码。之后,第二个 标记将数组的长度写出到浏览器页面,如 图 1 所示。图 1. simple.html 的输出好了!数据文件包含三本书,相应的 JavaScript 文件也包含三本书。它真的可以工作!通过函数加载上述第一个示例很简单,而且在大多数情况下可以发挥其作用,但它存在一些问题。第一个问题是对于数据何时被加载没有任何提示。如果数据是像页面那样被静态加载的,这不成问题。但是如果页面动态创建了一个 标记来按需加载数据,那么就很有必要知道 标记是何时完成的。实现

38、此功能的最好的方法是让编码了的数据调用一个 JavaScript 函数,而不是只设置数据。这个概念很重要,所以我将花一些时间来介绍一下为什么您必须要通过动态生成的 标记来加载数据。页面加载后,从服务器获得数据是 Web 2.0 的核心功能。一种方法是使用 AJAX 机制通过到服务器的调用来加载 XML。然而,出于安全性的原因,AJAX 机制只限于从单一域获取数据。这在大多数情况下都没有问题,但有时,您可能需要 JavaScript 代码运行在他人的页面上(例如,Google Maps)。在这种情况下从服务器获得数据的惟一方法是通过动态加载 标记。获悉 标记何时加载的最好的方法是让 标记返回的脚

39、本调用函数而不是简单地加载数据。清单 6 显示了在函数调用中编码的数据。清单 6. Function1.jsAddBooks( id: 1,name: Code Generation in Action,first: Jack,last: Herrington,publisher: Manning, id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly, id: 3,name: Podcasting Hacks,first: Jack,last: Herrington,publisher: OReilly )

40、;清单 7 给出了相应的 .html 文件。清单 7. Function1.htmlFunction 1 JS loadervar g_books = ;function AddBooks( books ) g_books = books; drawbooks( g_books );稍后将详细介绍 drawbooks 函数。这里重要的是了解一下页面如何定义 AddBooks 函数,该函数随后会由 function1.js 文件中的脚本调用。该 AddBooks 函数负责处理数据。而且被调用的 AddBooks 函数会向页面指示 标记被正确加载,并已加载完成。要创建 function1.js 文

41、件,我只对样式表稍微做了一点修改,如 清单 8 所示。清单 8. function1.xsl 样式表AddBooks( 1, id: ,name: ,first: ,last: ,publisher: );这里,我调用了一个函数,而不是简单地设置一个变量。这就是我所做的惟一更改。回到页面,我使用了 drawbooks 函数来构建书的表格,这样我就能够确认数据被正确编码和正确显示。此函数是在 drawbooks.js 内定义的,如 清单 9 所示。清单 9. Drawbooks.jsfunction drawbooks( books ) var elTable = document.create

42、Element( table ); for( var b in books ) var elTR = elTable.insertRow( -1 ); var elTD1 = elTR.insertCell( -1 ); elTD1.appendChild( document.createTextNode( booksb.id ) ); var elTD2 = elTR.insertCell( -1 ); elTD2.appendChild( document.createTextNode( ) ); var elTD3 = elTR.insertCell( -1 );

43、 elTD3.appendChild( document.createTextNode( booksb.first ) ); var elTD4 = elTR.insertCell( -1 ); elTD4.appendChild( document.createTextNode( booksb.last ) ); var elTD5 = elTR.insertCell( -1 ); elTD5.appendChild( document.createTextNode( booksb.publisher ) ); document.body.appendChild( elTable );这个简

44、单函数创建了一个表格节点,然后循环访问书的列表并为每本书创建一行,为每个数据元素分配一个单元格。此页面上的代码的结果如 图 2 所示。图 2. function1.html 的结果现在我就可以查看一下此页面的输出并确认来自原始 .xml 文件的一切均已被正确转换成 JavaScript 代码,且数据被发送到 AddData 函数并被正确添加到页面。细化函数调用技术我很喜欢函数调用这一技术,但我并不赞同将所有图书数据都放入一个块中。另一种方式是为每条记录采用一个调用,如 清单 10 所示。清单 10. Function2.jsAddBook( id: 1,name: Code Generatio

45、n in Action,first: Jack,last: Herrington,publisher: Manning );AddBook( id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly );.对 .html 页面只需做少许修改,如 清单 11 所示。清单 11. Function2.html.var g_books = ;function AddBook( book ) g_books.push( book ); .这里更改了 XSLT,以使函数调用驻留在 for-each 循环体内。清单 12 显

46、示了更新后的样式表。清单 12. function2.xsl.AddBook( id: ,name: ,first: ,last: ,publisher: );.对这个给定示例来说,这种更改看起来有些随意。但如果原始的 XML 数据集有多种数据类型,要为每种类型分配一个单独的函数调用会使 XSL 和页面上的 JavaScript 代码更为简单、更易于维护。编码对象对小的页面来讲,使用 JavaScript 函数没有问题。但对于大型项目,就需要使用 JavaScript 语言的一些面向对象特性。是的,JavaScript 语言可以处理对象而且可以处理得很好。清单 13 显示了如何创建带有数据的对

47、象。清单 13. Object1.jsg_books.push( new Book( id: 1,name: Code Generation in Action,first: Jack,last: Herrington,publisher: Manning ) );g_books.push( new Book( id: 2,name: PHP Hacks,first: Jack,last: Herrington,publisher: OReilly ) );在本例中,我只简单地向名为 g_books 的数组添加了 Book 对象。JavaScript 的对象创建与 Java、C# 或 C+ 编程语言的对象创建十分相似。都是一个 new 操作符后跟一个类名。参数放到随后的括号内。在本例中,我传入了一个带值的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论