Best K6 code snippet using html.Cite
goqueryuse.go
Source:goqueryuse.go
1package main2import (3 "errors"4 "fmt"5 "github.com/PuerkitoBio/goquery"6 "strings"7)8var html = `9<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">10<html xmlns="http://www.w3.org/1999/xhtml">11<head>12<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />13<title>é«æ¸
æç - 第2页 - é«æ¸
ä¸è½½å§ï¼ - Powered by Discuz!</title>14<meta name="keywords" content="é«æ¸
æç " />15<meta name="description" content="é«æ¸
æç ,é«æ¸
ä¸è½½å§ï¼" />16<meta name="generator" content="Discuz! X3.4" />17<meta name="author" content="Discuz! Team and Comsenz UI Team" />18<meta name="copyright" content="2001-2017 Comsenz Inc." />19<meta name="MSSmartTagsPreventParsing" content="True" />20<meta http-equiv="MSThemeCompatible" content="Yes" />21<base href="https://www.kan224.com/" /><link rel="stylesheet" type="text/css" href="data/cache/style_1_common.css?vUs" /><link rel="stylesheet" type="text/css" href="data/cache/style_1_forum_forumdisplay.css?vUs" /><script type="text/javascript">var STYLEID = '1', STATICURL = 'static/', IMGDIR = 'static/image/common', VERHASH = 'vUs', charset = 'utf-8', discuz_uid = '0', cookiepre = 'b9GW_2132_', cookiedomain = '', cookiepath = '/', showusercard = '1', attackevasive = '0', disallowfloat = 'newthread', creditnotice = '1|å¨æ|,2|éé±|,3|è´¡ç®|', defaultstyle = '', REPORTURL = 'aHR0cDovL3d3dy5rYW4yMjQuY29tL2ZvcnVtLTM2LTIuaHRtbA==', SITEURL = 'https://www.kan224.com/', JSPATH = 'static/js/', CSSPATH = 'data/cache/style_', DYNAMICURL = '';</script>22<script src="static/js/common.js?vUs" type="text/javascript"></script>23<meta name="application-name" content="é«æ¸
ä¸è½½å§ï¼" />24<meta name="msapplication-tooltip" content="é«æ¸
ä¸è½½å§ï¼" />25<meta name="msapplication-task" content="name=é¦é¡µ;action-uri=https://www.kan224.com/forum.php;icon-uri=https://www.kan224.com/static/image/common/bbs.ico" />26<link rel="archives" title="é«æ¸
ä¸è½½å§ï¼" href="https://www.kan224.com/archiver/" />27<link rel="alternate" type="application/rss+xml" title="é«æ¸
ä¸è½½å§ï¼ - é«æ¸
æç - 第2页" href="https://www.kan224.com/forum.php?mod=rss&fid=36&auth=0" />28<script src="static/js/forum.js?vUs" type="text/javascript"></script>29</head>30<body id="nv_forum" class="pg_forumdisplay" onkeydown="if(event.keyCode==27) return false;">31<div id="append_parent"></div><div id="ajaxwaitid"></div>32<div id="toptb" class="cl">33<div class="wp">34<div class="z"><a href="javascript:;" onclick="setHomepage('https://www.vcke.xyz/');">设为é¦é¡µ</a><a href="https://www.vcke.xyz/" onclick="addFavorite(this.href, 'é«æ¸
ä¸è½½å§ï¼');return false;">æ¶èæ¬ç«</a></div>35<div class="y">36<a id="switchblind" href="javascript:;" onclick="toggleBlind(this)" title="å¼å¯è¾
å©è®¿é®" class="switchblind">å¼å¯è¾
å©è®¿é®</a>37<a href="javascript:;" id="switchwidth" onclick="widthauto(this)" title="åæ¢å°å®½ç" class="switchwidth">åæ¢å°å®½ç</a>38</div>39</div>40</div>41<div id="qmenu_menu" class="p_pop blk" style="display: none;">42<div class="ptm pbw hm">43请 <a href="javascript:;" class="xi2" onclick="lsSubmit()"><strong>ç»å½</strong></a> å使ç¨å¿«æ·å¯¼èª<br />没æå¸å·ï¼<a href="member.php?mod=zbucihd4k" class="xi2 xw1">ç«å³æ³¨å</a>44</div>45<div id="fjump_menu" class="btda"></div></div><div class="wp a_h"><a href="https://cutt.ly/JgOQg3c"><img src="https://i.comss.pics/2020/12/03/960x80.gif" alt="960x80.gif" border="0" /></a></div><div id="hd">46<div class="wp">47<div class="hdc cl"><h2><a href="./" title="é«æ¸
ä¸è½½å§ï¼"><img src="static/image/common/logo.png" alt="é«æ¸
ä¸è½½å§ï¼" border="0" /></a></h2><script src="static/js/logging.js?vUs" type="text/javascript"></script>48<form method="post" autocomplete="off" id="lsform" action="member.php?mod=logging&action=login&loginsubmit=yes&infloat=yes&lssubmit=yes" onsubmit="return lsSubmit();">49<div class="fastlg cl">50<span id="return_ls" style="display:none"></span>51<div class="y pns">52<table cellspacing="0" cellpadding="0">53<tr>54<td>55<span class="ftid">56<select name="fastloginfield" id="ls_fastloginfield" width="40" tabindex="900">57<option value="username">ç¨æ·å</option>58<option value="email">Email</option>59</select>60</span>61<script type="text/javascript">simulateSelect('ls_fastloginfield')</script>62</td>63<td><input type="text" name="username" id="ls_username" autocomplete="off" class="px vm" tabindex="901" /></td>64<td class="fastlg_l"><label for="ls_cookietime"><input type="checkbox" name="cookietime" id="ls_cookietime" class="pc" value="2592000" tabindex="903" />èªå¨ç»å½</label></td>65<td> <a href="javascript:;" onclick="showWindow('login', 'member.php?mod=logging&action=login&viewlostpw=1')">æ¾åå¯ç </a></td>66</tr>67<tr>68<td><label for="ls_password" class="z psw_w">å¯ç </label></td>69<td><input type="password" name="password" id="ls_password" class="px vm" autocomplete="off" tabindex="902" /></td>70<td class="fastlg_l"><button type="submit" class="pn vm" tabindex="904" style="width: 75px;"><em>ç»å½</em></button></td>71<td> <a href="member.php?mod=zbucihd4k" class="xi2 xw1">ç«å³æ³¨å</a></td>72</tr>73</table>74<input type="hidden" name="quickforward" value="yes" />75<input type="hidden" name="handlekey" value="ls" />76</div>77</div>78</form>79</div>80<div id="nv">81<a href="javascript:;" id="qmenu" onmouseover="delayShow(this, function () {showMenu({'ctrlid':'qmenu','pos':'34!','ctrlclass':'a','duration':2});showForummenu(36);})">å¿«æ·å¯¼èª</a>82<ul><li class="a" id="mn_forum" ><a href="forum.php" hidefocus="true" title="BBS" >é¦é¡µ<span>BBS</span></a></li><li id="mn_N68fc" onmouseover="showMenu({'ctrlid':this.id,'ctrlclass':'hover','duration':2})"><a href="#" hidefocus="true" target="_blank" style="font-weight: bold;">å
è´¹18ç¦æ游</a></li><li id="mn_N0fd4" ><a href="https://3s.pw/9GMDY" hidefocus="true" target="_blank" style="font-weight: bold;">å·¥å£.R18 å
è²»ç¾å°å¥³éæ²</a></li></ul>83</div>84<ul class="p_pop h_pop" id="mn_N68fc_menu" style="display: none"><li><a href="https://dmmn17y868vex.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank" >ç½ç«çä¹³</a></li><li><a href="https://d2uyxuo46plvr.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank" >ä¸å½Hä¼ </a></li><li><a href="https://dpjoxi74vfy85.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank">é»é總è£</a></li><li><a href="https://d25k6ubz7qa2u1.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank">å°ç¥æ·«é</a></li><li><a href="https://d1ezng1oppe03v.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank" >ç±ç±å¦é¢</a></li><li><a href="https://d2z0vl0fubcyzw.cloudfront.net/?utm_source=17&utm_medium=CPC&utm_campaign=17&attributionid=17" hidefocus="true" target="_blank" >æ«ä¸çè
</a></li></ul><div id="mu" class="cl">85</div><div id="scbar" class="cl">86<form id="scbar_form" method="post" autocomplete="off" onsubmit="searchFocus($('scbar_txt'))" action="search.php?searchsubmit=yes" target="_blank">87<input type="hidden" name="mod" id="scbar_mod" value="search" />88<input type="hidden" name="formhash" value="b6acf023" />89<input type="hidden" name="srchtype" value="title" />90<input type="hidden" name="srhfid" value="36" />91<input type="hidden" name="srhlocality" value="forum::forumdisplay" />92<table cellspacing="0" cellpadding="0">93<tr>94<td class="scbar_icon_td"></td>95<td class="scbar_txt_td"><input type="text" name="srchtxt" id="scbar_txt" value="请è¾å
¥æç´¢å
容" autocomplete="off" x-webkit-speech speech /></td>96<td class="scbar_type_td"><a href="javascript:;" id="scbar_type" class="xg1" onclick="showMenu(this.id)" hidefocus="true">æç´¢</a></td>97<td class="scbar_btn_td"><button type="submit" name="searchsubmit" id="scbar_btn" sc="1" class="pn pnc" value="true"><strong class="xi2">æç´¢</strong></button></td>98<td class="scbar_hot_td">99<div id="scbar_hot">100<strong class="xw1">çæ: </strong>101<a href="search.php?mod=forum&srchtxt=%E6%B4%BB%E5%8A%A8&formhash=b6acf023&searchsubmit=true&source=hotsearch" target="_blank" class="xi2" sc="1">æ´»å¨</a>102<a href="search.php?mod=forum&srchtxt=%E4%BA%A4%E5%8F%8B&formhash=b6acf023&searchsubmit=true&source=hotsearch" target="_blank" class="xi2" sc="1">交å</a>103<a href="search.php?mod=forum&srchtxt=discuz&formhash=b6acf023&searchsubmit=true&source=hotsearch" target="_blank" class="xi2" sc="1">discuz</a>104</div>105</td>106</tr>107</table>108</form>109</div>110<ul id="scbar_type_menu" class="p_pop" style="display: none;"><li><a href="javascript:;" rel="curforum" fid="36" >æ¬ç</a></li><li><a href="javascript:;" rel="forum" class="curtype">å¸å</a></li><li><a href="javascript:;" rel="user">ç¨æ·</a></li></ul>111<script type="text/javascript">112initSearchmenu('scbar', '');113</script>114</div>115</div>116<div id="wp" class="wp">117<style id="diy_style" type="text/css"></style>118<!--[diy=diynavtop]--><div id="diynavtop" class="area"></div><!--[/diy]-->119<div id="pt" class="bm cl">120<div class="z">121<a href="./" class="nvhm" title="é¦é¡µ">é«æ¸
ä¸è½½å§ï¼</a><em>»</em><a href="forum.php">é¦é¡µ</a> <em>›</em> <a href="forum.php?gid=1">ååé«æ¸
BT</a><em>›</em> <a href="forum-36-1.html">é«æ¸
æç </a></div>122</div><div class="wp a_t"><table cellpadding="0" cellspacing="1"><tr><td width="100%"><!-- JuicyAds v3.1 -->123<script type="text/javascript" data-cfasync="false" async src="https://poweredby.jads.co/js/jads.js"></script>124<ins id="864492" data-width="728" data-height="102"></ins>125<script type="text/javascript" data-cfasync="false" async>(adsbyjuicy = window.adsbyjuicy || []).push({'adzone':864492});</script>126<!--JuicyAds END--></td></tr>127</table></div><div class="wp">128<!--[diy=diy1]--><div id="diy1" class="area"></div><!--[/diy]-->129</div>130<div class="boardnav">131<div id="ct" class="wp cl">132<div class="mn">133<div class="bm bml pbn">134<div class="bm_h cl">135<span class="y">136<a href="home.php?mod=spacecp&ac=favorite&type=forum&id=36&handlekey=favoriteforum&formhash=b6acf023" id="a_favorite" class="fa_fav" onclick="showWindow(this.id, this.href, 'get', 0);">æ¶èæ¬ç <strong class="xi1" id="number_favorite" >(<span id="number_favorite_num">12</span>)</strong></a>137<span class="pipe">|</span><a href="forum.php?mod=rss&fid=36&auth=0" class="fa_rss" target="_blank" title="RSS">订é
</a>138</span>139<h1 class="xs2">140<a href="forum-36-1.html">é«æ¸
æç </a>141<span class="xs1 xw0 i">ä»æ¥: <strong class="xi1">1</strong><b class="ico_increase"> </b><span class="pipe">|</span>主é¢: <strong class="xi1">22572</strong><span class="pipe">|</span>æå: <strong class="xi1" title="ä¸æ¬¡æå:11">20</strong><b class="ico_fall"> </b></span></h1>142</div>143</div>144<div class="drag">145<!--[diy=diy4]--><div id="diy4" class="area"><div id="frameWGX71I" class="frame move-span cl frame-1"><div id="frameWGX71I_left" class="column frame-1-c"><div id="frameWGX71I_left_temp" class="move-span temp"></div><div id="portal_block_8" class="block move-span"><div id="portal_block_8_content" class="dxb_bc"><div class="portal_block_summary"><table style="width:100%;" cellpadding="2" cellspacing="0" border="1" bordercolor="#000000">146 <tbody>147 <tr>148 <td>149 <p>150 <span style="font-family:KaiTi_GB2312;color:#009900;"> <a href="https://202900.com:2262?register=1" target="_blank"><span style="color:#009900;font-size:18px;"><strong>â¤ï¸ä¸å¤æ´å¯ 嫩模空å§ä»»ä½ é â¤ï¸</strong></span></a></span> 151 </p>152 </td>153 <td>154 <p>155 <span style="font-family:KaiTi_GB2312;color:#E56600;"> <a href="https://aoluoluo.info/?u=UIJYhNvfICHU" target="_blank"><span style="color:#E56600;font-size:18px;"><strong>å
¨å½å°å§ åå楼å¤</strong></span></a></span> 156 </p>157 </td>158 <td>159 <p>160 <span style="font-family:KaiTi_GB2312;color:#009900;"> <a href="https://cej.54647.blog/" target="_blank"><span style="color:#009900;font-size:18px;"><strong>å
è²»18ç¦ç¾å°å¥³æéæ²</strong></span></a></span> 161 </p>162 </td>163 <td>164 <p>165 <span style="font-family:KaiTi_GB2312;color:#E56600;"> <a href="http://www.uut92.com/" target="_blank"><span style="color:#E56600;font-size:18px;"><strong>å°æ¹¾uu裸èç´æ</strong></span></a></span> 166 </p>167 </td>168 </tr>169 </tbody>170</table>171<br /></div></div></div></div></div></div><!--[/diy]-->172</div>173<div class="bm bmw">174<div class="bm_h cl">175<h2>æ¨è主é¢</h2>176</div>177<div class="bm_c cl"><div class="cl"><ul class="xl xl2 cl"><li>178<a href="thread-60267-1-1.html" target="_blank">[HD/3.41G]261ARA-376ã絶対çç¾å°å¥³ã22æ³ãæå¼·SSSç´ããããã¡ãã5度ç®ã®åä¸ï¼ä¸ã¤æ³ãéããããã·ã¨è¦ç¿ãããåºé ã«ååãåºããããã«</a>179</li>180<li>181<a href="thread-27559-1-1.html" target="_blank">[HD/2.10G]SIRO-2571 ç´ äººAVä½é¨æ®å½±965 ã¿ãã 21æ³ å¦ç</a>182</li>183<li>184<a href="thread-65-1-1.html" target="_blank">[HD/5.45G]MIMK-020 æ¯å§Wç¸å§¦ æ¨ä¸ããã¿ æ²ç°æ梨</a>185</li>186<li>187<a href="thread-59564-1-1.html" target="_blank">[HD/2.42G]300MAAN-373 è¶
ãç´æ½®å¹ã13çºè¶
ãï¼å¤©ç¶ï¼ã¶ãã£åï¼ä¸æè°ç³»å·¨ä¹³ç¾å¥³ã¯ãé
ãç²¾åå¢å¼·å¤âªé
ã飲ãã ãå³çºæ
ï¼ï¼èå£ã®ãããã³ãã¶</a>188</li>189<li>190<a href="thread-48857-1-1.html" target="_blank">[HD/2.30G]SIRO-3710ãåæ®ãããããã§AVå¿åâAVä½é¨æ®å½± 875 ã㪠23æ³ ã¬ã¼ã«ãºãã¼ã¹ã¿ãã</a>191</li>192<li>193<a href="thread-125158-1-1.html" target="_blank">[HD/3.20G]DTT-026 éªèGã«ãããã¢ãè¬å¸«äººå¦» ä¸ãç¬è« ä¸åºãæé¡æ¿åã»ãã¯ã¹ æ¸
æ¥ãªéªè巨乳ç¾äººå¦»ã«å¤§éä¸åºã3é£çºï¼ï¼ï¼</a>194</li>195<li>196<a href="thread-40261-1-1.html" target="_blank">[HD/3.75G]320MMGH-045 ã²ãã¿ã¡ãã ä¿®å¦æ
è¡ ãã¸ãã¯ãã©ã¼å· ä¿®å¦æ
è¡ä¸ã«ã·ã§ã¼ãã«ããã®å¥³ã®åãå¦å¥³åæ¥ï¼</a>197</li>198<li>199<a href="thread-78050-1-1.html" target="_blank">[HD/4.58G]SSNI-432 ãã¼ãã©Fã«ãããã£ã±ãã§å
¨åã¢ãã¼ã«ãã¦ãã彼女ã®å·¨ä¹³å¦¹ã¨ãèªæã«è² ãã¡ããæä½ãªåã ä¸ä¸æ äº</a>200</li>201<li>202<a href="thread-57253-1-1.html" target="_blank">[HD/2.88G]259LUXU-1086 ã©ã°ã¸ã¥TV 1072 快楽ã«è²ªæ¬²ããããã¥ã¼ã¹ãã£ã¹ã¿ã¼åã³ï¼å¤©æ§ã®ãMæ°è³ªã¯ã¬ãï¼éææ溢ããç¾ããã¨ã¯å¯¾ç
§ã«</a>203</li>204<li>205<a href="thread-21033-1-1.html" target="_blank">[HD/2.67G]259LUXU-734 ã©ã°ã¸ã¥TV 724 é´æ涼å 34æ³ ãã¢ãè¬å¸«</a>206</li>207</ul>208</div></div>209</div>210<div id="pgt" class="bm bw0 pgs cl">211<span id="fd_page_top"><div class="pg"><a href="forum-36-1.html" class="prev"> </a><a href="forum-36-1.html">1</a><strong>2</strong><a href="forum-36-3.html">3</a><a href="forum-36-4.html">4</a><a href="forum-36-5.html">5</a><a href="forum-36-6.html">6</a><a href="forum-36-7.html">7</a><a href="forum-36-8.html">8</a><a href="forum-36-9.html">9</a><a href="forum-36-10.html">10</a><a href="forum-36-1129.html" class="last">... 1129</a><label><input type="text" name="custompage" class="px" size="2" title="è¾å
¥é¡µç ï¼æå车快é跳转" value="2" onkeydown="if(event.keyCode==13) {window.location='forum.php?mod=forumdisplay&fid=36&page='+this.value;; doane(event);}" /><span title="å
± 1129 页"> / 1129 页</span></label><a href="forum-36-3.html" class="nxt">ä¸ä¸é¡µ</a></div></span>212<span class="pgb y" ><a href="forum.php">è¿ å</a></span>213<a href="javascript:;" id="newspecial" onmouseover="$('newspecial').id = 'newspecialtmp';this.id = 'newspecial';showMenu({'ctrlid':this.id})" onclick="showWindow('newthread', 'forum.php?mod=post&action=newthread&fid=36')" title="åæ°å¸"><img src="static/image/common/pn_post.png" alt="åæ°å¸" /></a></div>214<div id="threadlist" class="tl bm bmw">215<div class="th">216<table cellspacing="0" cellpadding="0">217<tr>218<th colspan="2">219<div class="tf">220<span id="atarget" onclick="setatarget(1)" class="y" title="å¨æ°çªå£ä¸æå¼å¸å">æ°çª</span>221<a id="filter_special" href="javascript:;" class="showmenu xi2" onclick="showMenu(this.id)">å
¨é¨ä¸»é¢</a> 222<a href="forum.php?mod=forumdisplay&fid=36&filter=lastpost&orderby=lastpost" class="xi2">ææ°</a> 223<a href="forum.php?mod=forumdisplay&fid=36&filter=heat&orderby=heats" class="xi2">çé¨</a> 224<a href="forum.php?mod=forumdisplay&fid=36&filter=hot" class="xi2">çå¸</a> 225<a href="forum.php?mod=forumdisplay&fid=36&filter=digest&digest=1" class="xi2">ç²¾å</a> 226<a id="filter_dateline" href="javascript:;" class="showmenu xi2" onclick="showMenu(this.id)">æ´å¤</a> 227<span id="clearstickthread" style="display: none;">228<span class="pipe">|</span>229<a href="javascript:;" onclick="clearStickThread()" class="xi2" title="æ¾ç¤ºç½®é¡¶">æ¾ç¤ºç½®é¡¶</a>230</span>231</div>232</th>233<td class="by">ä½è
</td>234<td class="num">åå¤/æ¥ç</td>235<td class="by">æåå表</td>236</tr>237</table>238</div>239<div class="bm_c">240<script type="text/javascript">var lasttime = 1626005543;var listcolspan= '5';</script>241<div id="forumnew" style="display:none"></div>242<form method="post" autocomplete="off" name="moderate" id="moderate" action="forum.php?mod=topicadmin&action=moderate&fid=36&infloat=yes&nopost=yes">243<input type="hidden" name="formhash" value="b6acf023" />244<input type="hidden" name="listextra" value="page%3D2" />245<table summary="forum_36" cellspacing="0" cellpadding="0" id="threadlisttableid">246<tbody id="separatorline" class="emptb"><tr><td class="icn"></td><th></th><td class="by"></td><td class="num"></td><td class="by"></td></tr></tbody>247<tbody id="normalthread_334074">248<tr>249<td class="icn">250<a href="thread-334074-1-2.html" title="æ°çªå£æå¼" target="_blank">251<img src="static/image/common/folder_common.gif" />252</a>253</td>254<th class="common">255<a href="javascript:;" id="content_334074" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='334074';CONTENT_ID='normalthread_334074';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>256 <a href="thread-334074-1-2.html" onclick="atarget(this)" class="s xst">[HD/2.33G]435MFC-116ãèè¢ãã³ã¯ä¹³é¦ã®ç¾å°å¥³ãããã¨ãä»èã§ãæã¡å¸°ãããè¦æãã¡ãããã¼ãã¼å¥³åã¨çãã¡ä¸åºãï¼ã¹ã¿ã¤ã«æ群ã§é
æçãã...</a>257<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />258</th>259<td class="by">260<cite>261<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>262<em><span><span title="2021-7-8">3 天å</span></span></em>263</td>264<td class="num"><a href="thread-334074-1-2.html" class="xi2">0</a><em>596</em></td>265<td class="by">266<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>267<em><a href="forum.php?mod=redirect&tid=334074&goto=lastpost#lastpost"><span title="2021-7-8 10:43">3 天å</span></a></em>268</td>269</tr>270</tbody>271<tbody id="normalthread_334072">272<tr>273<td class="icn">274<a href="thread-334072-1-2.html" title="æ°çªå£æå¼" target="_blank">275<img src="static/image/common/folder_common.gif" />276</a>277</td>278<th class="common">279<a href="javascript:;" id="content_334072" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='334072';CONTENT_ID='normalthread_334072';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>280 <a href="thread-334072-1-2.html" onclick="atarget(this)" class="s xst">[HD/2.54G]406FTHT-016ããMéè±å®£è¨ï¼æ¿ãã¹ã¤ã©ãï¼ã¨ãã¬ï¼ä¹³é¦ããµããã¼ã¿ã¼çµ¶å¥ã親ã®è¨ããªãåªççããMã«è±¹å¤ï¼è¦ªã«å
ç·ã§ãã¤ãã³ï¼ç´
ãæ...</a>281<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />282</th>283<td class="by">284<cite>285<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>286<em><span><span title="2021-7-8">3 天å</span></span></em>287</td>288<td class="num"><a href="thread-334072-1-2.html" class="xi2">0</a><em>417</em></td>289<td class="by">290<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>291<em><a href="forum.php?mod=redirect&tid=334072&goto=lastpost#lastpost"><span title="2021-7-8 10:40">3 天å</span></a></em>292</td>293</tr>294</tbody>295<tbody id="normalthread_334071">296<tr>297<td class="icn">298<a href="thread-334071-1-2.html" title="æ°çªå£æå¼" target="_blank">299<img src="static/image/common/folder_common.gif" />300</a>301</td>302<th class="common">303<a href="javascript:;" id="content_334071" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='334071';CONTENT_ID='normalthread_334071';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>304 <a href="thread-334071-1-2.html" onclick="atarget(this)" class="s xst">[HD/2.99G]300NTK-588 ç®æãæå¼·ãã¡ã«ã¯ã°ã©ãã«ï¼ï¼ã ãå°»Fã«ããã®æ¬²æ
åæèªçºããã£ã®ã¨ãã¨ã度æºç¹ã®å¤©ç¶ç¾å°å¥³ã®ã°ã©ãã¢æ®å½±ä¼ã«AVç·åªã...</a>305<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />306</th>307<td class="by">308<cite>309<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>310<em><span><span title="2021-7-8">3 天å</span></span></em>311</td>312<td class="num"><a href="thread-334071-1-2.html" class="xi2">0</a><em>482</em></td>313<td class="by">314<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>315<em><a href="forum.php?mod=redirect&tid=334071&goto=lastpost#lastpost"><span title="2021-7-8 10:37">3 天å</span></a></em>316</td>317</tr>318</tbody>319<tbody id="normalthread_334070">320<tr>321<td class="icn">322<a href="thread-334070-1-2.html" title="æ°çªå£æå¼" target="_blank">323<img src="static/image/common/folder_common.gif" />324</a>325</td>326<th class="common">327<a href="javascript:;" id="content_334070" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='334070';CONTENT_ID='normalthread_334070';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>328 <a href="thread-334070-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.74G]300MIUM-711ãJã«ãã116cm&ãâã³ãã¾ãã£ã¨çµ¡ãåãé·ï½ãã¨ãèãã«æããæ©ã¾ã§è¿«ãåããã¡åãï¼ãªããªããç®ã«ããããªãã¬ã¢å·¨ä¹³ã...</a>329<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />330</th>331<td class="by">332<cite>333<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>334<em><span><span title="2021-7-8">3 天å</span></span></em>335</td>336<td class="num"><a href="thread-334070-1-2.html" class="xi2">0</a><em>486</em></td>337<td class="by">338<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>339<em><a href="forum.php?mod=redirect&tid=334070&goto=lastpost#lastpost"><span title="2021-7-8 10:35">3 天å</span></a></em>340</td>341</tr>342</tbody>343<tbody id="normalthread_334069">344<tr>345<td class="icn">346<a href="thread-334069-1-2.html" title="æ°çªå£æå¼" target="_blank">347<img src="static/image/common/folder_common.gif" />348</a>349</td>350<th class="common">351<a href="javascript:;" id="content_334069" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='334069';CONTENT_ID='normalthread_334069';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>352 <a href="thread-334069-1-2.html" onclick="atarget(this)" class="s xst">[HD/2.51G]200GANA-2511 ãã¸è»æ´¾ãåæ®ã 1651 ãã£ã¨ããã¦ããã«è¦ãã¦Hãªè©±ã«ãæå¤ã¨å¯å®¹ï¼æµãããããããªæ§æ ¼ã«æ¼¬ãè¾¼ãã§è¬ç¤¼ãæ示ããã¨â¦...</a>353<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />354</th>355<td class="by">356<cite>357<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>358<em><span><span title="2021-7-8">3 天å</span></span></em>359</td>360<td class="num"><a href="thread-334069-1-2.html" class="xi2">0</a><em>408</em></td>361<td class="by">362<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>363<em><a href="forum.php?mod=redirect&tid=334069&goto=lastpost#lastpost"><span title="2021-7-8 10:30">3 天å</span></a></em>364</td>365</tr>366</tbody>367<tbody id="normalthread_333692">368<tr>369<td class="icn">370<a href="thread-333692-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">371<img src="static/image/common/folder_lock.gif" />372</a>373</td>374<th class="lock">375<a href="javascript:;" id="content_333692" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333692';CONTENT_ID='normalthread_333692';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>376 <a href="thread-333692-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.18G]WAAA-067 ããã£ï¼ä»ãä¸ã«åºããã§ããï¼ãæ©æ¼ãã´ãããæ´çºå¾ã®å»¶é·ãã¹ãã³ã§æããã®è¿½æä¸åºãï¼ï¼ ç½æ¡ã¯ãª</a>377<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />378</th>379<td class="by">380<cite>381<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>382<em><span><span title="2021-7-7">4 天å</span></span></em>383</td>384<td class="num"><a href="thread-333692-1-2.html" class="xi2">0</a><em>685</em></td>385<td class="by">386<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>387<em><a href="forum.php?mod=redirect&tid=333692&goto=lastpost#lastpost"><span title="2021-7-7 11:42">4 天å</span></a></em>388</td>389</tr>390</tbody>391<tbody id="normalthread_333691">392<tr>393<td class="icn">394<a href="thread-333691-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">395<img src="static/image/common/folder_lock.gif" />396</a>397</td>398<th class="lock">399<a href="javascript:;" id="content_333691" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333691';CONTENT_ID='normalthread_333691';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>400 <a href="thread-333691-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.53G]STARS-415 ãä¸çã§1çªã¨ãããã¹ãã¦ã¿ãªãï¼ãçæ§ãå¿ãã¦èãã¾ããæããåãçµãããªãæ¥å»ã ç´åã¾ãª</a>401<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />402</th>403<td class="by">404<cite>405<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>406<em><span><span title="2021-7-7">4 天å</span></span></em>407</td>408<td class="num"><a href="thread-333691-1-2.html" class="xi2">0</a><em>534</em></td>409<td class="by">410<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>411<em><a href="forum.php?mod=redirect&tid=333691&goto=lastpost#lastpost"><span title="2021-7-7 11:39">4 天å</span></a></em>412</td>413</tr>414</tbody>415<tbody id="normalthread_333690">416<tr>417<td class="icn">418<a href="thread-333690-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">419<img src="static/image/common/folder_lock.gif" />420</a>421</td>422<th class="lock">423<a href="javascript:;" id="content_333690" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333690';CONTENT_ID='normalthread_333690';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>424 <a href="thread-333690-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.58G]STARS-389 æ»ã¬ã»ã©å«ããã¦ããé£äººã®ãã¢è¦ªç¶ããæ°å©å¦»ãã¡ãã¡ãã»ã¢ãã¢ã¸è便å¨ã«å¬âæ´è³ã§ãã¡ããã¾ããã æ¬åºé´</a>425<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />426</th>427<td class="by">428<cite>429<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>430<em><span><span title="2021-7-7">4 天å</span></span></em>431</td>432<td class="num"><a href="thread-333690-1-2.html" class="xi2">0</a><em>586</em></td>433<td class="by">434<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>435<em><a href="forum.php?mod=redirect&tid=333690&goto=lastpost#lastpost"><span title="2021-7-7 11:36">4 天å</span></a></em>436</td>437</tr>438</tbody>439<tbody id="normalthread_333689">440<tr>441<td class="icn">442<a href="thread-333689-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">443<img src="static/image/common/folder_lock.gif" />444</a>445</td>446<th class="lock">447<a href="javascript:;" id="content_333689" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333689';CONTENT_ID='normalthread_333689';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>448 <a href="thread-333689-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.53G]SSIS-099 ã¹ã¯æ°´ããã¢ã«çããã¦â¦ ç²çã¹ãã¼ã«ã¼ã®çæ°çãªçæ®ã«å
¨ã¦ãæãã輪âãããå¶æå°å¥³ å±±å´æ°´æ</a>449<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />450</th>451<td class="by">452<cite>453<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>454<em><span><span title="2021-7-7">4 天å</span></span></em>455</td>456<td class="num"><a href="thread-333689-1-2.html" class="xi2">0</a><em>567</em></td>457<td class="by">458<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>459<em><a href="forum.php?mod=redirect&tid=333689&goto=lastpost#lastpost"><span title="2021-7-7 11:31">4 天å</span></a></em>460</td>461</tr>462</tbody>463<tbody id="normalthread_333688">464<tr>465<td class="icn">466<a href="thread-333688-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">467<img src="static/image/common/folder_lock.gif" />468</a>469</td>470<th class="lock">471<a href="javascript:;" id="content_333688" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333688';CONTENT_ID='normalthread_333688';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>472 <a href="thread-333688-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.14G]PPPD-937 ç¥ã¹ã¬ã³ãã¼å·¨ä¹³ãå§ãããæéç¡å¶éã§ã¶ã£éãå°ç²¾ããã¦ãããé«ç´ä¸çã¡ã¼ã«ã¼ç´å¶ã¡ã³ãºã¨ã¹ã å¤å¸ã¾ãã</a>473<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />474</th>475<td class="by">476<cite>477<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>478<em><span><span title="2021-7-7">4 天å</span></span></em>479</td>480<td class="num"><a href="thread-333688-1-2.html" class="xi2">0</a><em>636</em></td>481<td class="by">482<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>483<em><a href="forum.php?mod=redirect&tid=333688&goto=lastpost#lastpost"><span title="2021-7-7 11:28">4 天å</span></a></em>484</td>485</tr>486</tbody>487<tbody id="normalthread_333687">488<tr>489<td class="icn">490<a href="thread-333687-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">491<img src="static/image/common/folder_lock.gif" />492</a>493</td>494<th class="lock">495<a href="javascript:;" id="content_333687" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333687';CONTENT_ID='normalthread_333687';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>496 <a href="thread-333687-1-2.html" onclick="atarget(this)" class="s xst">[HD/6.21G]HUNTB-049 é«ç¬ããªã»å°æ¢
ããªã»çç°ããªã»è¾»ããã ãã¼ãã©ï¼ãã£ãã½ã¼ã«Ãå°å³é ã巨乳義å§=ä¹³é¦ãéããã»ã©ãã£ã±ãèãåãã¦ããã£...</a>497<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />498</th>499<td class="by">500<cite>501<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>502<em><span><span title="2021-7-7">4 天å</span></span></em>503</td>504<td class="num"><a href="thread-333687-1-2.html" class="xi2">0</a><em>501</em></td>505<td class="by">506<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>507<em><a href="forum.php?mod=redirect&tid=333687&goto=lastpost#lastpost"><span title="2021-7-7 11:26">4 天å</span></a></em>508</td>509</tr>510</tbody>511<tbody id="normalthread_333686">512<tr>513<td class="icn">514<a href="thread-333686-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">515<img src="static/image/common/folder_lock.gif" />516</a>517</td>518<th class="lock">519<a href="javascript:;" id="content_333686" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333686';CONTENT_ID='normalthread_333686';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>520 <a href="thread-333686-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.52G]DTT-081 8å¹´éã»ãã¯ã¹ã¬ã¹ ã·ã³ã°ã«ãã¶ã¼ ç¾å·¨ä¹³ä¸å¦æ ¡æ師 ç¾ååããã 47æ³ ä¸åºã3P AVããã¥ã¼ï¼ï¼ é·å¹´æã¦ä½ããè±æºããã£ãã«ã¡ã©...</a>521<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />522</th>523<td class="by">524<cite>525<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>526<em><span><span title="2021-7-7">4 天å</span></span></em>527</td>528<td class="num"><a href="thread-333686-1-2.html" class="xi2">0</a><em>506</em></td>529<td class="by">530<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>531<em><a href="forum.php?mod=redirect&tid=333686&goto=lastpost#lastpost"><span title="2021-7-7 11:21">4 天å</span></a></em>532</td>533</tr>534</tbody>535<tbody id="normalthread_333685">536<tr>537<td class="icn">538<a href="thread-333685-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">539<img src="static/image/common/folder_lock.gif" />540</a>541</td>542<th class="lock">543<a href="javascript:;" id="content_333685" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333685';CONTENT_ID='normalthread_333685';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>544 <a href="thread-333685-1-2.html" onclick="atarget(this)" class="s xst">[HD/4.77G]ABW-111 ã¢ãªãã« å¶æç¾å°å¥³ã¨å®å
¨ä¸»è¦³ã§éããæ§æ¥3SEXã ï¼06 ã¨ããã§çé
¸ã£ã±ãéæ¥ã°ã©ãã£ãã£ãå
¨ã¦ããªãè¦ç¹ã§ä½é¨ãã165å</a>545<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />546</th>547<td class="by">548<cite>549<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>550<em><span><span title="2021-7-7">4 天å</span></span></em>551</td>552<td class="num"><a href="thread-333685-1-2.html" class="xi2">0</a><em>511</em></td>553<td class="by">554<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>555<em><a href="forum.php?mod=redirect&tid=333685&goto=lastpost#lastpost"><span title="2021-7-7 11:19">4 天å</span></a></em>556</td>557</tr>558</tbody>559<tbody id="normalthread_333684">560<tr>561<td class="icn">562<a href="thread-333684-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">563<img src="static/image/common/folder_lock.gif" />564</a>565</td>566<th class="lock">567<a href="javascript:;" id="content_333684" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333684';CONTENT_ID='normalthread_333684';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>568 <a href="thread-333684-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.13G]WAAA-077 çµé»ãéããåãæ³ãã¦ããããã¤ãã®å
輩⦠ãã¼ãã©é¨å±çããå¼¾ãåºããã£ã±ããã«ã³ã«ææ
¢ã§ããå¤æãã¾ã§ã¤ãªã¾ãã£ãï¼...</a>569<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />570</th>571<td class="by">572<cite>573<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>574<em><span><span title="2021-7-7">4 天å</span></span></em>575</td>576<td class="num"><a href="thread-333684-1-2.html" class="xi2">0</a><em>480</em></td>577<td class="by">578<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>579<em><a href="forum.php?mod=redirect&tid=333684&goto=lastpost#lastpost"><span title="2021-7-7 11:14">4 天å</span></a></em>580</td>581</tr>582</tbody>583<tbody id="normalthread_333683">584<tr>585<td class="icn">586<a href="thread-333683-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">587<img src="static/image/common/folder_lock.gif" />588</a>589</td>590<th class="lock">591<a href="javascript:;" id="content_333683" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333683';CONTENT_ID='normalthread_333683';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>592 <a href="thread-333683-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.91G]WAAA-075 å°ç²¾ãã¦ãç·æ½®å¹ãã¦ããâãããã¶ãç¶ãã¦ãããããªï¼ï¼ ã¤ã¼ã¿</a>593<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />594</th>595<td class="by">596<cite>597<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>598<em><span><span title="2021-7-7">4 天å</span></span></em>599</td>600<td class="num"><a href="thread-333683-1-2.html" class="xi2">0</a><em>450</em></td>601<td class="by">602<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>603<em><a href="forum.php?mod=redirect&tid=333683&goto=lastpost#lastpost"><span title="2021-7-7 11:11">4 天å</span></a></em>604</td>605</tr>606</tbody>607<tbody id="normalthread_333682">608<tr>609<td class="icn">610<a href="thread-333682-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">611<img src="static/image/common/folder_lock.gif" />612</a>613</td>614<th class="lock">615<a href="javascript:;" id="content_333682" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333682';CONTENT_ID='normalthread_333682';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>616 <a href="thread-333682-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.13G]WAAA-074 ãããã¤ãã¦ãã£ã¦ã°ãï¼ãç¶æ
ã§ä½åº¦ãä¸åºãï¼ ç½å·ãã</a>617<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />618</th>619<td class="by">620<cite>621<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>622<em><span><span title="2021-7-7">4 天å</span></span></em>623</td>624<td class="num"><a href="thread-333682-1-2.html" class="xi2">0</a><em>410</em></td>625<td class="by">626<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>627<em><a href="forum.php?mod=redirect&tid=333682&goto=lastpost#lastpost"><span title="2021-7-7 11:09">4 天å</span></a></em>628</td>629</tr>630</tbody>631<tbody id="normalthread_333681">632<tr>633<td class="icn">634<a href="thread-333681-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">635<img src="static/image/common/folder_lock.gif" />636</a>637</td>638<th class="lock">639<a href="javascript:;" id="content_333681" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333681';CONTENT_ID='normalthread_333681';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>640 <a href="thread-333681-1-2.html" onclick="atarget(this)" class="s xst">[HD/2.04G]SIRO-4526ãåæ®ãããæºãã天ç¶Gä¹³ãçã¿ã³å±ã§åãGã«ãããå§ãããã¹ã±ããªæ¬æ§ããããåºããè©ãã¦ããæ¸
æ¥é¡ã¯å¿
è¦ã å¿åç´ äººã...</a>641<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />642</th>643<td class="by">644<cite>645<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>646<em><span><span title="2021-7-7">4 天å</span></span></em>647</td>648<td class="num"><a href="thread-333681-1-2.html" class="xi2">0</a><em>537</em></td>649<td class="by">650<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>651<em><a href="forum.php?mod=redirect&tid=333681&goto=lastpost#lastpost"><span title="2021-7-7 11:02">4 天å</span></a></em>652</td>653</tr>654</tbody>655<tbody id="normalthread_333680">656<tr>657<td class="icn">658<a href="thread-333680-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">659<img src="static/image/common/folder_lock.gif" />660</a>661</td>662<th class="lock">663<a href="javascript:;" id="content_333680" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333680';CONTENT_ID='normalthread_333680';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>664 <a href="thread-333680-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.78G]MIDE-945 Hã«ãããã£ã±ããã¤ãºãªæå°ãã«ã³ã¼ã¹ é«ç»è³ªæºãä¹³ALLãã¤ãºãªæå° ä¸å±±ãµã¿ã</a>665<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />666</th>667<td class="by">668<cite>669<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>670<em><span><span title="2021-7-7">4 天å</span></span></em>671</td>672<td class="num"><a href="thread-333680-1-2.html" class="xi2">0</a><em>474</em></td>673<td class="by">674<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>675<em><a href="forum.php?mod=redirect&tid=333680&goto=lastpost#lastpost"><span title="2021-7-7 10:59">4 天å</span></a></em>676</td>677</tr>678</tbody>679<tbody id="normalthread_333679">680<tr>681<td class="icn">682<a href="thread-333679-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">683<img src="static/image/common/folder_lock.gif" />684</a>685</td>686<th class="lock">687<a href="javascript:;" id="content_333679" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333679';CONTENT_ID='normalthread_333679';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>688 <a href="thread-333679-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.07G]MIDE-944 å·¨æ ¹çå¾ã®èªãã«è² ãã¦ãã¾ã£ãæ°ä»»å¥³æ師 ç´é³è¯</a>689<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />690</th>691<td class="by">692<cite>693<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>694<em><span><span title="2021-7-7">4 天å</span></span></em>695</td>696<td class="num"><a href="thread-333679-1-2.html" class="xi2">0</a><em>502</em></td>697<td class="by">698<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>699<em><a href="forum.php?mod=redirect&tid=333679&goto=lastpost#lastpost"><span title="2021-7-7 10:55">4 天å</span></a></em>700</td>701</tr>702</tbody>703<tbody id="normalthread_333678">704<tr>705<td class="icn">706<a href="thread-333678-1-2.html" title="å
³éçä¸»é¢ - æ°çªå£æå¼" target="_blank">707<img src="static/image/common/folder_lock.gif" />708</a>709</td>710<th class="lock">711<a href="javascript:;" id="content_333678" class="showcontent y" title="æ´å¤æä½" onclick="CONTENT_TID='333678';CONTENT_ID='normalthread_333678';showMenu({'ctrlid':this.id,'menuid':'content_menu'})"></a>712 <a href="thread-333678-1-2.html" onclick="atarget(this)" class="s xst">[HD/3.76G]MIDE-943 æ度çä¸ããããã£ãä¸æ¥ä¸ã¶ã£éãã§ãã¡ã¾ãã ãã³ã¹ãããç¡éãªã¼ã¬ãºã ãã¡ã»ã¯æ½®å¹ãè¶
絶é é«æ©ãããå</a>713<img src="static/image/filetype/common.gif" alt="attachment" title="é件" align="absmiddle" />714</th>715<td class="by">716<cite>717<a href="space-uid-14.html" c="1" style="color: #999900;">kindler</a></cite>718<em><span><span title="2021-7-7">4 天å</span></span></em>719</td>720<td class="num"><a href="thread-333678-1-2.html" class="xi2">0</a><em>527</em></td>721<td class="by">722<cite><a href="space-username-kindler.html" c="1">kindler</a></cite>723<em><a href="forum.php?mod=redirect&tid=333678&goto=lastpost#lastpost"><span title="2021-7-7 10:53">4 天å</span></a></em>724</td>725</tr>726</tbody>727</table><!-- end of table "forum_G[fid]" branch 1/3 -->728</form>729</div>730</div>731<div id="filter_special_menu" class="p_pop" style="display:none" change="location.href='forum.php?mod=forumdisplay&fid=36&filter='+$('filter_special').value">732<ul>733<li><a href="forum-36-1.html">å
¨é¨ä¸»é¢</a></li>734<li><a href="forum.php?mod=forumdisplay&fid=36&filter=specialtype&specialtype=poll">æ票</a></li></ul>735</div>736<div id="filter_reward_menu" class="p_pop" style="display:none" change="forum.php?mod=forumdisplay&fid=36&filter=specialtype&specialtype=reward&rewardtype='+$('filter_reward').value">737<ul>738<li><a href="forum.php?mod=forumdisplay&fid=36&filter=specialtype&specialtype=reward">å
¨é¨æ¬èµ</a></li>739<li><a href="forum.php?mod=forumdisplay&fid=36&filter=specialtype&specialtype=reward&rewardtype=1">è¿è¡ä¸</a></li></ul>740</div>741<div id="filter_dateline_menu" class="p_pop" style="display:none">742<ul class="pop_moremenu">743<li>æåº: 744<a href="forum.php?mod=forumdisplay&fid=36&filter=author&orderby=dateline" class="xw1">åå¸æ¶é´</a><span class="pipe">|</span>745<a href="forum.php?mod=forumdisplay&fid=36&filter=reply&orderby=replies" >åå¤/æ¥ç</a><span class="pipe">|</span>746<a href="forum.php?mod=forumdisplay&fid=36&filter=reply&orderby=views" >æ¥ç</a>747</li>748<li>æ¶é´: 749<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline" class="xw1">å
¨é¨æ¶é´</a><span class="pipe">|</span>750<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline&dateline=86400" >ä¸å¤©</a><span class="pipe">|</span>751<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline&dateline=172800" >两天</a><span class="pipe">|</span>752<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline&dateline=604800" >ä¸å¨</a><span class="pipe">|</span>753<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline&dateline=2592000" >ä¸ä¸ªæ</a><span class="pipe">|</span>754<a href="forum.php?mod=forumdisplay&fid=36&orderby=dateline&filter=dateline&dateline=7948800" >ä¸ä¸ªæ</a>755</li>756</ul>757</div>758<div id="filter_orderby_menu" class="p_pop" style="display:none">759<ul>760<li><a href="forum-36-1.html">é»è®¤æåº</a></li>761<li><a href="forum.php?mod=forumdisplay&fid=36&filter=author&orderby=dateline">åå¸æ¶é´</a></li>762<li><a href="forum.php?mod=forumdisplay&fid=36&filter=reply&orderby=replies">åå¤/æ¥ç</a></li>763<li><a href="forum.php?mod=forumdisplay&fid=36&filter=reply&orderby=views">æ¥ç</a></li>764<li><a href="forum.php?mod=forumdisplay&fid=36&filter=lastpost&orderby=lastpost">æåå表</a></li>765<li><a href="forum.php?mod=forumdisplay&fid=36&filter=heat&orderby=heats">çé¨</a></li>766</ul>767</div>768<a class="bm_h" href="javascript:;" rel="forum.php?mod=forumdisplay&fid=36&page=3" curpage="2" id="autopbn" totalpage="1129" picstyle="0" forumdefstyle="">ä¸ä¸é¡µ »</a>769<script src="static/js/autoloadpage.js?vUs" type="text/javascript"></script>770<div class="bm bw0 pgs cl">771<span id="fd_page_bottom"><div class="pg"><a href="forum-36-1.html" class="prev"> </a><a href="forum-36-1.html">1</a><strong>2</strong><a href="forum-36-3.html">3</a><a href="forum-36-4.html">4</a><a href="forum-36-5.html">5</a><a href="forum-36-6.html">6</a><a href="forum-36-7.html">7</a><a href="forum-36-8.html">8</a><a href="forum-36-9.html">9</a><a href="forum-36-10.html">10</a><a href="forum-36-1129.html" class="last">... 1129</a><label><input type="text" name="custompage" class="px" size="2" title="è¾å
¥é¡µç ï¼æå车快é跳转" value="2" onkeydown="if(event.keyCode==13) {window.location='forum.php?mod=forumdisplay&fid=36&page='+this.value;; doane(event);}" /><span title="å
± 1129 页"> / 1129 页</span></label><a href="forum-36-3.html" class="nxt">ä¸ä¸é¡µ</a></div></span>772<span class="pgb y"><a href="forum.php">è¿ å</a></span>773<a href="javascript:;" id="newspecialtmp" onmouseover="$('newspecial').id = 'newspecialtmp';this.id = 'newspecial';showMenu({'ctrlid':this.id})" onclick="showWindow('newthread', 'forum.php?mod=post&action=newthread&fid=36')" title="åæ°å¸"><img src="static/image/common/pn_post.png" alt="åæ°å¸" /></a></div>774<!--[diy=diyfastposttop]--><div id="diyfastposttop" class="area"><div id="frameKrlJ6L" class="frame move-span cl frame-1"><div id="frameKrlJ6L_left" class="column frame-1-c"><div id="frameKrlJ6L_left_temp" class="move-span temp"></div><div id="portal_block_12" class="block move-span"><div id="portal_block_12_content" class="dxb_bc"><div class="portal_block_summary"><table style="width:100%;" cellpadding="2" cellspacing="0" border="1" bordercolor="#000000">775 <tbody>776 <tr>777 <td>778 <p>779 <span style="font-family:KaiTi_GB2312;color:#009900;"> <a href="https://202900.com:2262?register=1" target="_blank"><span style="color:#009900;font-size:18px;"><strong>â¤ï¸ä¸å¤æ´å¯ 嫩模空å§ä»»ä½ é â¤ï¸</strong></span></a></span> 780 </p>781 </td>782 <td>783 <p>784 <span style="font-family:KaiTi_GB2312;color:#E56600;"> <a href="https://aoluoluo.info/?u=UIJYhNvfICHU" target="_blank"><span style="color:#E56600;font-size:18px;"><strong>å
¨å½å°å§ åå楼å¤</strong></span></a></span> 785 </p>786 </td>787 <td>788 <p>789 <span style="font-family:KaiTi_GB2312;color:#009900;"> <a href="https://cej.54647.blog/" target="_blank"><span style="color:#009900;font-size:18px;"><strong>å
è²»18ç¦ç¾å°å¥³æéæ²</strong></span></a></span> 790 </p>791 </td>792 <td>793 <p>794 <span style="font-family:KaiTi_GB2312;color:#E56600;"> <a href="http://www.uut92.com/" target="_blank"><span style="color:#E56600;font-size:18px;"><strong>å°æ¹¾uu裸èç´æ</strong></span></a></span> 795 </p>796 </td>797 </tr>798 </tbody>799</table>800<br /></div></div></div></div></div></div><!--[/diy]-->801<script type="text/javascript">802var postminchars = parseInt('10');803var postmaxchars = parseInt('200000');804var disablepostctrl = parseInt('0');805var fid = parseInt('36');806</script>807<div id="f_pst" class="bm">808<div class="bm_h">809<h2>å¿«éåå¸</h2>810</div>811<div class="bm_c">812<form method="post" autocomplete="off" id="fastpostform" action="forum.php?mod=post&action=newthread&fid=36&topicsubmit=yes&infloat=yes&handlekey=fastnewpost" onSubmit="return fastpostvalidate(this)">813<div id="fastpostreturn" style="margin:-5px 0 5px"></div>814<div class="pbt cl">815<input type="text" id="subject" name="subject" class="px" value="" onkeyup="strLenCalc(this, 'checklen', 200);" tabindex="11" style="width: 25em" />816<span>è¿å¯è¾å
¥ <strong id="checklen">200</strong> 个å符</span>817</div>818<div class="cl">819<div id="fastsmiliesdiv" class="y"><div id="fastsmiliesdiv_data"><div id="fastsmilies"></div></div></div><div class="hasfsl" id="fastposteditor">820<div class="tedt">821<div class="bar">822<span class="y">823<a href="forum.php?mod=post&action=newthread&fid=36" onclick="switchAdvanceMode(this.href);doane(event);">é«çº§æ¨¡å¼</a>824</span><script src="static/js/seditor.js?vUs" type="text/javascript"></script>825<div class="fpd">826<a href="javascript:;" title="æåå ç²" class="fbld">B</a>827<a href="javascript:;" title="设置æåé¢è²" class="fclr" id="fastpostforecolor">Color</a>828<a id="fastpostimg" href="javascript:;" title="å¾ç" class="fmg">Image</a>829<a id="fastposturl" href="javascript:;" title="æ·»å é¾æ¥" class="flnk">Link</a>830<a id="fastpostquote" href="javascript:;" title="å¼ç¨" class="fqt">Quote</a>831<a id="fastpostcode" href="javascript:;" title="代ç " class="fcd">Code</a>832<a href="javascript:;" class="fsml" id="fastpostsml">Smilies</a>833</div></div>834<div class="area">835<div class="pt hm">836æ¨éè¦ç»å½åæå¯ä»¥åå¸ <a href="member.php?mod=logging&action=login" onclick="showWindow('login', this.href)" class="xi2">ç»å½</a> | <a href="member.php?mod=zbucihd4k" class="xi2">ç«å³æ³¨å</a>837</div>838</div>839</div>840</div>841<div id="seccheck_fastpost">842</div>843<input type="hidden" name="formhash" value="b6acf023" />844<input type="hidden" name="usesig" value="" />845</div>846<p class="ptm pnpost">847<a href="home.php?mod=spacecp&ac=credit&op=rule&fid=36" class="y" target="_blank">æ¬ç积åè§å</a>848<button type="submit" onmouseover="checkpostrule('seccheck_fastpost', 'ac=newthread');this.onmouseover=null" name="topicsubmit" id="fastpostsubmit" value="topicsubmit" tabindex="13" class="pn pnc"><strong>å表å¸å</strong></button>849</p>850</form>851</div>852</div>853<!--[diy=diyforumdisplaybottom]--><div id="diyforumdisplaybottom" class="area"></div><!--[/diy]-->854</div>855</div>856</div>857<div class="wp mtn">858<!--[diy=diy3]--><div id="diy3" class="area"></div><!--[/diy]-->859</div>860<script>fixed_top_nv();</script> </div>861<div id="ft" class="wp cl">862<div id="flk" class="y">863<p>864<a href="archiver/" >Archiver</a><span class="pipe">|</span><a href="forum.php?mobile=yes" >ææºç</a><span class="pipe">|</span><a href="/cdn-cgi/l/email-protection#781e1714141f0d010a0f38080a170c171615191114561b10" style="font-weight: bold;color: red">DMCA</a><span class="pipe">|</span><strong><a href="https://www.889dog.com/" target="_blank">é«æ¸
ä¸è½½å§ï¼</a></strong>865<!-- Global site tag (gtag.js) - Google Analytics -->866<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script async src="https://www.googletagmanager.com/gtag/js?id=UA-151112001-1"></script>867<script>868 window.dataLayer = window.dataLayer || [];869 function gtag(){dataLayer.push(arguments);}870 gtag('js', new Date());871 gtag('config', 'UA-151112001-1');872</script>873</p>874<p class="xs0">875GMT+8, 2021-7-11 20:12<span id="debuginfo">876, Processed in 0.258063 second(s), 18 queries877, Gzip On, Redis On.878</span>879</p>880</div>881<div id="frt">882<p>Powered by <strong><a href="http://www.discuz.net" target="_blank">Discuz!</a></strong> <em>X3.4</em></p>883<p class="xs0">© 2001-2017 <a href="http://www.comsenz.com" target="_blank">Comsenz Inc.</a></p>884</div></div>885<script src="home.php?mod=misc&ac=sendmail&rand=1626005543" type="text/javascript"></script>886<div id="scrolltop">887<span hidefocus="true"><a title="è¿å顶é¨" onclick="window.scrollTo('0','0')" class="scrolltopa" ><b>è¿å顶é¨</b></a></span>888<span>889<a href="forum.php" hidefocus="true" class="returnboard" title="è¿åçå"><b>è¿åçå</b></a>890</span>891</div>892<script type="text/javascript">_attachEvent(window, 'scroll', function () { showTopLink(); });checkBlind();</script>893</body>894</html>895`896func main() {897 doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))898 if err != nil {899 msg := fmt.Sprintf("html 转æ¢doc失败: %s", err.Error())900 panic(errors.New(msg))901 }902 //doc.Find("a[class$='s xst']").Each(func(i int, s *goquery.Selection) {903 doc.Find("a:contains(ä¸å±±ãµ)").Each(func(i int, s *goquery.Selection) {904 fmt.Println(s.Text())905 })906}...
sanitize_test.go
Source:sanitize_test.go
1// Copyright 2011 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.4package template5import (6 "bytes"7 "io/ioutil"8 "os"9 "path/filepath"10 "regexp"11 "strings"12 "testing"13 "github.com/google/safehtml"14 "github.com/google/safehtml/testconversions"15)16func TestDynamicElementNamePrefixEscaped(t *testing.T) {17 for _, test := range [...]struct {18 input, want string19 }{20 {21 `<{{if 1}}area{{else}}link{{end}} title="bar">`,22 `<area title="bar">`,23 },24 {25 `<{{ "FOO" }} title="bar">`,26 `<FOO title="bar">`,27 },28 {29 `<{{ "FOO" }}a title="bar">`,30 `<FOOa title="bar">`,31 },32 {33 `<{{"script"}}>{{"doEvil()"}}</{{"script"}}>`,34 `<script>doEvil()</script>`,35 },36 } {37 tmpl := Must(New(test.input).Parse(stringConstant(test.input)))38 var b bytes.Buffer39 err := tmpl.Execute(&b, nil)40 if err != nil {41 t.Errorf("%s : template execution failed:\n%s", test.input, err)42 continue43 }44 if got := b.String(); got != test.want {45 t.Errorf("%s : escaped output: got\n\t%s\nwant\n\t%s", test.input, got, test.want)46 }47 }48}49func TestConditionalElementOrAttributeAllowed(t *testing.T) {50 data := struct {51 A safehtml.Identifier52 B []string53 C, D bool54 X string55 }{56 A: safehtml.IdentifierFromConstant("id"),57 B: []string{"foo", "bar"},58 C: false,59 D: true,60 X: "hello",61 }62 for _, test := range [...]string{63 // Conditional element names that lead to the same element content sanitization64 // contexts are allowed.65 `{{if .C}}<object></object>{{end}}{{ .X }}`,66 `{{if .C}}<a>{{end}}{{ .X }}`,67 `{{if .C}}<a{{else}}<b{{end}}>{{ .X }}`,68 `{{if .C}}<a>{{else}}<b>{{end}}{{ .X }}`,69 `{{if .C}}<a>{{else if .D}}<b>{{else}}<h1>{{end}}{{ .X }}`,70 `{{range .B}}<object></object>{{end}}{{ .X }}`,71 `{{range .B}}<a>{{end}}{{ .X }}`,72 `{{range .B}}<a>{{else}}<b>{{end}}{{ .X }}`,73 `{{with .C}}<object></object>{{end}}{{ .X }}`,74 `{{with .C}}<a>{{end}}{{ .X }}`,75 `{{with .C}}<a{{else}}<b{{end}}>{{ .X }}`,76 `{{with .C}}<a>{{else}}<b>{{end}}{{ .X }}`,77 // Conditional element or attribute names that lead to the same attribute value sanitization78 // contexts are allowed.79 `<input{{if .C}} checked{{end}} name="foo">`,80 `{{if .C}}<img{{else}}<audio{{end}} src="{{ .X }}">`,81 `{{if .C}}<img{{else if .D}}<audio{{else}}<input{{end}} src="{{ .X }}">`,82 `<label {{if .C}}lang{{else}}translate{{end}}="{{ .A }}">`,83 `<label {{if .C}}lang{{else if .D}}translate{{else}}spellcheck{{end}}="{{ .A }}">`,84 `<label {{range .B}}lang{{else}}translate{{end}}="{{ .A }}">`,85 `{{with .C}}<img{{else}}<audio{{end}} src="{{ .A }}">`,86 `<label {{with .C}}lang{{else}}translate{{end}}="{{ .A }}">`,87 // Conditional insertion of an attribute-value pair with a fixed attribute name is allowed, even if the88 // attributes have different sanitization contexts.89 `<a {{if .C}}id="{{ .A }}"{{end}}>foo</a>`,90 `<a {{if .C}}id="{{ .A }}"{{else}}href="{{ .X }}"{{end}}>foo</a>`,91 `<a {{if .C}}id="{{ .A }}"{{else if .D}}href="{{ .X }}"{{else}}class="{{ .X }}"{{end}}>foo</a>`,92 `<a {{with .C}}id="{{ .A }}"{{end}}>foo</a>`,93 `<a {{with .C}}id="{{ .A }}"{{else}}href="{{ .X }}"{{end}}>foo</a>`,94 } {95 tmpl := Must(New(test).Parse(stringConstant(test)))96 var b bytes.Buffer97 err := tmpl.Execute(&b, data)98 if err != nil {99 t.Errorf("unexpected an error for template %s :\n\t%s", test, err)100 continue101 }102 }103}104func TestConditionalElementOrAttributeErrorMessage(t *testing.T) {105 // The conditional branch error message prefix should only be emitted for templates with106 // a conditional branching error.107 conditionalBranchMsgPattern := regexp.MustCompile(`conditional branch with .* results in sanitization error: `)108 for _, test := range [...]struct {109 in, err string110 hasConditionalBranchMsg bool111 }{112 {113 `<option foo="{{ . }}">`,114 `actions must not occur in the "foo" attribute value context of a "option" element`,115 false,116 },117 {118 `<option {{if .X}}foo{{else}}bar{{end}}="{{ . }}">`,119 `actions must not occur in the "foo" attribute value context of a "option" element`,120 true,121 },122 {123 `<foo>{{ . }}</foo>`,124 `actions must not occur in the element content context of a "foo" element`,125 false,126 },127 {128 `{{if .X}}<foo>{{else}}<bar>{{end}}{{ . }}</imaginaryelement>`,129 `actions must not occur in the element content context of a "foo" element`,130 true,131 },132 } {133 tmpl := Must(New("").Parse(stringConstant(test.in)))134 var b bytes.Buffer135 err := tmpl.Execute(&b, nil)136 if err == nil {137 t.Fatalf("expected an error")138 }139 got := err.Error()140 hasConditionalBranchMsg := conditionalBranchMsgPattern.MatchString(got)141 if hasConditionalBranchMsg && !test.hasConditionalBranchMsg {142 t.Errorf("%s : error message unexpectedly reports conditional branching failure:\n\t%q", test.in, got)143 } else if !hasConditionalBranchMsg && test.hasConditionalBranchMsg {144 t.Errorf("%s : error message does not report conditional branching failure:\n\t%q", test.in, got)145 }146 if !strings.Contains(got, test.err) {147 t.Errorf("error\n\t%s\ndoes not contain expected string\n\t%s", got, test.err)148 }149 }150}151// TestNilEmptySliceData test that nil and empty slice data is rendered sensibly and without error.152func TestNilEmptySliceData(t *testing.T) {153 tt := Must(New("").Parse(`<b>{{ . }}</b>`))154 for _, test := range [...]struct {155 desc string156 in interface{}157 want string158 }{159 {"nil", nil, testNilEmptySliceDataNilWant},160 {"zero-length slice", []string{}, "<b>[]</b>"},161 {"slice containing nil", []interface{}{nil}, "<b>[<nil>]</b>"},162 } {163 var b bytes.Buffer164 err := tt.Execute(&b, test.in)165 if err != nil {166 t.Fatalf("%s: unexpected error: %s", test.desc, err)167 }168 if got := b.String(); got != test.want {169 t.Errorf("%s: got %q, want %q", test.desc, got, test.want)170 }171 }172}173var testConversionFuncs = FuncMap{174 "makeHTMLForTest": func(s string) safehtml.HTML { return testconversions.MakeHTMLForTest(s) },175 "makeURLForTest": func(s string) safehtml.URL { return testconversions.MakeURLForTest(s) },176 "makeTrustedResourceURLForTest": func(s string) safehtml.TrustedResourceURL { return testconversions.MakeTrustedResourceURLForTest(s) },177 "makeStyleForTest": func(s string) safehtml.Style { return testconversions.MakeStyleForTest(s) },178 "makeStyleSheetForTest": func(s string) safehtml.StyleSheet { return testconversions.MakeStyleSheetForTest(s) },179 "makeScriptForTest": func(s string) safehtml.Script { return testconversions.MakeScriptForTest(s) },180 "makeIdentifierForTest": func(s string) safehtml.Identifier { return testconversions.MakeIdentifierForTest(s) },181}182func TestSanitize(t *testing.T) {183 data := struct {184 T bool185 A, E []string186 QueryParams map[string]string187 }{188 T: true,189 A: []string{"<a>", "<b>"},190 E: []string{},191 QueryParams: map[string]string{"k1": "v1", "k2": "v2", "k3": "v3"},192 }193 for _, test := range [...]struct {194 input string195 output string196 err string197 }{198 // Overescaping.199 {200 input: `Hello, {{"<Cincinnati>" | html}}!`,201 output: "Hello, <Cincinnati>!",202 err: ``,203 },204 {205 input: `Hello, {{html "<Cincinnati>"}}!`,206 output: "Hello, <Cincinnati>!",207 err: ``,208 },209 {210 input: `{{with "<Cincinnati>"}}{{$msg := .}}Hello, {{$msg}}!{{end}}`,211 output: "Hello, <Cincinnati>!",212 err: ``,213 },214 // Assignment.215 {216 input: `{{if $x := "<Hello>"}}{{$x}}{{end}}`,217 output: "<Hello>",218 err: ``,219 },220 // if else.221 {222 input: `{{if 1}}Hello{{end}}, {{"<Cincinnati>"}}!`,223 output: `Hello, <Cincinnati>!`,224 err: ``,225 },226 {227 input: `{{if 0}}{{"<Hello>"}}{{else}}{{"<Goodbye>"}}{{end}}!`,228 output: `<Goodbye>!`,229 err: ``,230 },231 // with body.232 {233 input: `{{with "<Hello>"}}{{.}}{{end}}`,234 output: "<Hello>",235 err: ``,236 },237 // with-else.238 {239 input: `{{with .E}}{{.}}{{else}}{{"<Hello>"}}{{end}}`,240 output: "<Hello>",241 err: ``,242 },243 // range body.244 {245 input: "{{range .A}}{{.}}{{end}}",246 output: "<a><b>",247 err: ``,248 },249 // range-else.250 {251 input: `{{range .E}}{{.}}{{else}}{{"<Hello>"}}{{end}}`,252 output: "<Hello>",253 err: ``,254 },255 // Non-string value.256 {257 input: "{{.T}}",258 output: "true",259 err: ``,260 },261 // Multiple attributes.262 {263 input: `<a width="1" value="{{"<Hello>"}}">`,264 output: `<a width="1" value="<Hello>">`,265 err: ``,266 },267 // HTML comment ignored.268 {269 input: `<b>Hello, <!-- name of world -->{{"<Cincinnati>"}}</b>`,270 output: "<b>Hello, <Cincinnati></b>",271 err: ``,272 },273 {274 input: `<!-- -{{""}}-> <script -->{{"doEvil()//"}}<!-- -{{""}}-> </script -->`,275 output: `doEvil()//`,276 err: ``,277 },278 // HTML comment not first < in text node.279 {280 input: "<<!-- -->!--",281 output: "<!--",282 err: ``,283 },284 {285 input: `<<!-- -->script>{{"doEvil()"}}<<!-- -->/script>`,286 output: `<script>doEvil()</script>`,287 err: ``,288 },289 // Split HTML comment.290 {291 input: `<b>Hello, <!-- name of {{if 1}}city -->{{"<Cincinnati>"}}{{else}}world -->{{"<Boston>"}}{{end}}</b>`,292 output: "<b>Hello, <Cincinnati></b>",293 err: ``,294 },295 // No comment injection.296 {297 input: `<{{"!--"}}`,298 output: `<!--`,299 err: ``,300 },301 // No RCDATA end tag injection.302 {303 input: `<textarea><{{"/textarea "}}...</textarea>`,304 output: `<textarea></textarea ...</textarea>`,305 err: ``,306 },307 // Template-author-controlled '<' <script> body not overescaped.308 {309 input: `<script>var b = 1 < 2</script>`,310 output: `<script>var b = 1 < 2</script>`,311 err: ``,312 },313 // Template-author controlled HTML metacharacters in <style>.314 {315 input: `<style>a[href=~"<"] > b { color: blue }</style>`,316 output: `<style>a[href=~"<"] > b { color: blue }</style>`,317 err: ``,318 },319 // HTML substitution commented out.320 {321 input: `<p><!-- {{"<Hello>"}} --></p>`,322 output: "<p></p>",323 err: ``,324 },325 // Comment ends flush with start.326 {327 input: `<!--{{.}}--><p>Hello</p>`,328 output: "<p>Hello</p>",329 err: ``,330 },331 // HTML normalization.332 {333 input: "a < b",334 output: "a < b",335 err: ``,336 },337 {338 input: "a << b",339 output: "a << b",340 err: ``,341 },342 {343 input: "a<<!-- --><!-- -->b",344 output: "a<b",345 err: ``,346 },347 // HTML doctype not normalized.348 {349 input: "<!DOCTYPE html>Hello, World!",350 output: "<!DOCTYPE html>Hello, World!",351 err: ``,352 },353 // HTML doctype not case-insensitive.354 {355 input: "<!doCtYPE htMl>Hello, World!",356 output: "<!doCtYPE htMl>Hello, World!",357 err: ``,358 },359 // No doctype injection.360 {361 input: `<!{{"DOCTYPE"}}`,362 output: "<!DOCTYPE",363 err: ``,364 },365 // range values sanitized.366 {367 input: "<textarea>{{range .A}}{{.}}{{end}}</textarea>",368 output: "<textarea><a><b></textarea>",369 err: ``,370 },371 // Actions outside of HTML element expect HTML.372 {373 input: `<head>title</head>{{ "<b>foo</b>" }}`,374 output: `<head>title</head><b>foo</b>`,375 err: ``,376 },377 {378 input: `<head>title</head>{{ makeHTMLForTest "<b>foo</b>" }}`,379 output: `<head>title</head><b>foo</b>`,380 err: ``,381 },382 {383 input: `{{ "<b>foo</b>" }}`,384 output: `<b>foo</b>`,385 err: ``,386 },387 {388 input: `{{ makeHTMLForTest "<b>foo</b>" }}`,389 output: `<b>foo</b>`,390 err: ``,391 },392 // Attribute value contexts that allow untrusted strings.393 {394 input: `<link media="{{ "print" }}">`,395 output: `<link media="print">`,396 err: ``,397 },398 {399 input: `<form method="{{ "get<" }}"></form>`,400 output: `<form method="get<"></form>`, // untrusted string is still HTML-escaped401 err: ``,402 },403 // Element content contexts that expect HTML.404 {405 input: `<span>{{ "<b>foo</b>" }}</span>`,406 output: `<span><b>foo</b></span>`,407 err: ``,408 },409 {410 input: `<span>{{ makeHTMLForTest "<b>foo</b>" }}</span>`,411 output: `<span><b>foo</b></span>`,412 err: ``,413 },414 // Attribute value contexts that expect HTML.415 {416 input: `<iframe srcdoc="{{ "<a href=\"https://www.foo.com\">foo</a>" }}">{{ "<b>bar</b>" }}</iframe>`,417 output: ``,418 err: `expected a safehtml.HTML value`,419 },420 {421 input: `<iframe srcdoc="{{ makeHTMLForTest "<a href=\"https://www.foo.com\">foo</a>" }}">{{ makeHTMLForTest "<b>bar</b>" }}</iframe>`,422 output: `<iframe srcdoc="<a href="https://www.foo.com">foo</a>"><b>bar</b></iframe>`,423 err: ``,424 },425 // Attribute value contexts that expect URL.426 // safehtml.URL values should still be HTML-escaped even after bypassing URL sanitization.427 {428 input: `<q cite="{{ "data:,\"><script>alert('pwned!')</script>" }}">foo</q>`,429 output: `<q cite="about:invalid#zGoSafez">foo</q>`,430 err: ``,431 },432 {433 input: `<q cite="{{ makeURLForTest "data:,\"><script>alert('pwned!')</script>" }}">foo</q>`,434 output: `<q cite="data:,%22%3e%3cscript%3ealert%28%27pwned!%27%29%3c/script%3e">foo</q>`,435 err: ``,436 },437 {438 input: `<link rel="alternate" href="{{ "data:,\"><script>alert('pwned!')</script>" }}">`,439 output: `<link rel="alternate" href="about:invalid#zGoSafez">`,440 err: ``,441 },442 {443 input: `<link rel="alternate" href="{{ makeURLForTest "data:,\"><script>alert('pwned!')</script>" }}">`,444 output: `<link rel="alternate" href="data:,%22%3e%3cscript%3ealert%28%27pwned!%27%29%3c/script%3e">`,445 err: ``,446 },447 {448 input: `<q cite="{{ "data:,\"><script>alert('pwned!')</script>" }}my/path">foo</q>`,449 output: `<q cite="about:invalid#zGoSafezmy/path">foo</q>`,450 err: ``,451 },452 {453 input: `<q cite="{{ makeURLForTest "http://www.foo.com/" }}my/path">foo</q>`,454 output: `<q cite="http://www.foo.com/my/path">foo</q>`,455 err: ``,456 },457 {458 input: `<q cite="{{ makeURLForTest "http://www.foo.com/" }}main?a={{ "b&c=d" }}">foo</q>`,459 output: `<q cite="http://www.foo.com/main?a=b%26c%3dd">foo</q>`,460 err: ``,461 },462 {463 input: `<q cite="{{ makeURLForTest "http://www.foo.com/" }}main?a={{ "w&x" }}&b={{ "y#z" }}">foo</q>`,464 output: `<q cite="http://www.foo.com/main?a=w%26x&b=y%23z">foo</q>`,465 err: ``,466 },467 {468 input: `<q cite="http://www.foo.com/{{ "multiple/path/segments" }}">foo</q>`,469 output: `<q cite="http://www.foo.com/multiple/path/segments">foo</q>`,470 err: ``,471 },472 {473 input: `<q cite="/foo?q={{ "bar&x=baz" }}">foo</q>`,474 output: `<q cite="/foo?q=bar%26x%3dbaz">foo</q>`,475 err: ``,476 },477 {478 input: `<q cite="/foo?q={{ "bar&x=baz" }}&j={{ "bar&x=baz" }}">foo</q>`,479 output: `<q cite="/foo?q=bar%26x%3dbaz&j=bar%26x%3dbaz">foo</q>`,480 err: ``,481 },482 {483 input: `<q cite="http://www.foo.com/{{ "multiple/path/segments" }}?q={{ "bar&x=baz" }}">foo</q>`,484 output: `<q cite="http://www.foo.com/multiple/path/segments?q=bar%26x%3dbaz">foo</q>`,485 err: ``,486 },487 {488 input: `<q cite="?q={{ "myQuery" }}&hl={{ "en" }}">foo</q>`,489 output: `<q cite="?q=myQuery&hl=en">foo</q>`,490 err: ``,491 },492 {493 input: `<q cite="j{{ "avascript:alert(1)" }}">foo</q>`,494 output: ``,495 err: `action cannot be interpolated into the "cite" URL attribute value of this "q" element: URL prefix "j" is unsafe; it might be interpreted as part of a scheme`,496 },497 {498 input: `<q cite="javascript:{{ "alert(1)" }}">foo</q>`,499 output: ``,500 err: `action cannot be interpolated into the "cite" URL attribute value of this "q" element: URL prefix "javascript:" contains an unsafe scheme`,501 },502 {503 input: `<q cite=" {{ "not interpreted as a URL prefix" }}">foo</q>`,504 output: ``,505 err: `action cannot be interpolated into the "cite" URL attribute value of this "q" element: URL prefix " " contains whitespace or control characters`,506 },507 {508 input: `<q cite="{{ "http://www.foo.com/?q=hello\\.world" }}">foo</q>`,509 output: `<q cite="http://www.foo.com/?q=hello%5c.world">foo</q>`,510 err: ``,511 },512 {513 input: `<q cite="/path/{{ ".." }}/{{ "foo" }}?n1=v1">foo</q>`,514 output: `<q cite="/path/../foo?n1=v1">foo</q>`,515 err: ``,516 },517 {518 input: `<q cite="/foo?a=b{{range $k, $v := .QueryParams}}&{{$k}}={{$v}}{{end}}">foo</q>`,519 output: `<q cite="/foo?a=b&k1=v1&k2=v2&k3=v3">foo</q>`,520 err: ``,521 },522 // Safe type values that are inappropriate for the HTML context get523 // unpacked into string and sanitized at run-time.524 {525 input: `<span>{{ makeScriptForTest "alert(\"foo\");" }}</span>`,526 output: `<span>alert("foo");</span>`,527 err: ``,528 },529 {530 input: `<q cite="{{ makeStyleForTest "width: 1em;height: 1em;" }}">foo</q>`,531 output: `<q cite="about:invalid#zGoSafez">foo</q>`,532 err: ``,533 },534 // Attribute value contexts that expect TrustedResouceURL.535 {536 input: `<link href="{{ "data:,foo" }}">`,537 output: ``,538 err: `expected a safehtml.TrustedResourceURL value`,539 },540 {541 input: `<link href="{{ makeTrustedResourceURLForTest "data:,foo" }}">`,542 output: `<link href="data:,foo">`,543 err: ``,544 },545 {546 input: `<iframe src="{{ "data:,foo" }}"></iframe>`,547 output: ``,548 err: `expected a safehtml.TrustedResourceURL value`,549 },550 {551 input: `<iframe src="{{ makeTrustedResourceURLForTest "data:,foo" }}"></iframe>`,552 output: `<iframe src="data:,foo"></iframe>`,553 err: ``,554 },555 {556 input: `<link href="{{ "data:,foo" }}my/path">`,557 output: ``,558 err: `expected a safehtml.TrustedResourceURL value`,559 },560 {561 input: `<link href="{{ makeTrustedResourceURLForTest "https://www.foo.com/" }}my/path">`,562 output: `<link href="https://www.foo.com/my/path">`,563 err: ``,564 },565 {566 input: `<link href=" {{ "not interpreted as a URL prefix" }}">`,567 output: ``,568 err: `action cannot be interpolated into the "href" URL attribute value of this "link" element: URL prefix " " contains whitespace or control characters`,569 },570 {571 // Note: the error message here is confusing, since "main?a=" isn't actually the prefix of the URL.572 // However, having a URL with a dynamic prefix and suffix and a static middle portion is probably573 // never a valid use case, so we are ok with this failing confusingly.574 input: `<link href="{{ makeTrustedResourceURLForTest "https://www.foo.com/" }}main?a={{ "b&c=d" }}">`,575 output: ``,576 err: `action cannot be interpolated into the "href" URL attribute value of this "link" element: "main?a=" is a disallowed TrustedResourceURL prefix`,577 },578 {579 input: `<link href="/foo?q={{ "myQuery" }}&hl={{ "en" }}">`,580 output: `<link href="/foo?q=myQuery&hl=en">`,581 err: ``,582 },583 {584 input: `<link href="/path/{{ ".." }}/{{ "foo" }}?n1=v1">`,585 output: ``,586 err: `cannot substitute ".." after TrustedResourceURL prefix: ".." is disallowed`,587 },588 {589 // Invalid UTF-8.590 input: `<link href="/foo?{{ "\xFF\xFE\xFD" }}">`,591 output: `<link href="/foo?%ff%fe%fd">`,592 err: ``,593 },594 {595 // Supplementary codepoints.596 input: `<link href="/foo?{{ "\U00012345" }}">`,597 output: `<link href="/foo?%f0%92%8d%85">`,598 err: ``,599 },600 {601 input: `<link href="https://www.foo.com/{{ "main.html" }}">`,602 output: `<link href="https://www.foo.com/main.html">`,603 err: ``,604 },605 {606 input: `<link href="https://www.foo.com/{{ "multiple/path/segments" }}">`,607 output: `<link href="https://www.foo.com/multiple%2fpath%2fsegments">`,608 err: ``,609 },610 {611 input: `<link href="/foo?q={{ "bar&x=baz" }}">`,612 output: `<link href="/foo?q=bar%26x%3dbaz">`,613 err: ``,614 },615 {616 input: `<link href="https://www.foo.com/{{ "multiple/path/segments" }}?q={{ "bar&x=baz" }}">`,617 output: `<link href="https://www.foo.com/multiple%2fpath%2fsegments?q=bar%26x%3dbaz">`,618 err: ``,619 },620 {621 input: `<link href="http://www.foo.com/{{ "main.html" }}">`,622 output: ``,623 err: `action cannot be interpolated into the "href" URL attribute value of this "link" element: "http://www.foo.com/" is a disallowed TrustedResourceURL prefix`,624 },625 {626 input: `<link href="j{{ "avascript:alert(1)" }}">`,627 output: ``,628 err: `action cannot be interpolated into the "href" URL attribute value of this "link" element: "j" is a disallowed TrustedResourceURL prefix`,629 },630 {631 input: `<link href="javascript:{{ "alert(1)" }}">`,632 output: ``,633 err: `action cannot be interpolated into the "href" URL attribute value of this "link" element: "javascript:" is a disallowed TrustedResourceURL prefix`,634 },635 // Attribute value contexts that accept both URL and TrustedResouceURL.636 {637 // URL sanitization applied to untrusted string.638 input: `<source src="{{ "data:,\"><script>alert('pwned!')</script>" }}">`,639 output: `<source src="about:invalid#zGoSafez">`,640 err: ``,641 },642 {643 input: `<source src="{{ makeURLForTest "data:,\"><script>alert('pwned!')</script>" }}"> <source src="{{ makeTrustedResourceURLForTest "data:,foo" }}">`,644 output: `<source src="data:,%22%3e%3cscript%3ealert%28%27pwned!%27%29%3c/script%3e"> <source src="data:,foo">`,645 err: ``,646 },647 {648 input: `<source src="{{ "data:,\"><script>alert('pwned!')</script>" }}my/path">`,649 output: `<source src="about:invalid#zGoSafezmy/path">`,650 err: ``,651 },652 {653 input: `<source src="{{ makeURLForTest "http://www.foo.com/" }}my/path">`,654 output: `<source src="http://www.foo.com/my/path">`,655 err: ``,656 },657 {658 input: `<source src="{{ makeURLForTest "http://www.foo.com/" }}main?a={{ "b&c=d" }}">`,659 output: `<source src="http://www.foo.com/main?a=b%26c%3dd">`,660 err: ``,661 },662 {663 input: `<source src="{{ makeURLForTest "http://www.foo.com/" }}main?a={{ "w&x" }}&b={{ "y#z" }}">`,664 output: `<source src="http://www.foo.com/main?a=w%26x&b=y%23z">`,665 err: ``,666 },667 {668 input: `<source src="http://www.foo.com/{{ "multiple/path/segments" }}">`,669 output: `<source src="http://www.foo.com/multiple/path/segments">`,670 err: ``,671 },672 {673 input: `<source src="/foo?q={{ "bar&x=baz" }}">`,674 output: `<source src="/foo?q=bar%26x%3dbaz">`,675 err: ``,676 },677 {678 input: `<source src="/foo?q={{ "bar&x=baz" }}&j={{ "bar&x=baz" }}">`,679 output: `<source src="/foo?q=bar%26x%3dbaz&j=bar%26x%3dbaz">`,680 err: ``,681 },682 {683 input: `<source src="http://www.foo.com/{{ "multiple/path/segments" }}?q={{ "bar&x=baz" }}">`,684 output: `<source src="http://www.foo.com/multiple/path/segments?q=bar%26x%3dbaz">`,685 err: ``,686 },687 {688 input: `<source src="?q={{ "myQuery" }}&hl={{ "en" }}">`,689 output: `<source src="?q=myQuery&hl=en">`,690 err: ``,691 },692 {693 input: `<source src="{{ "http://www.foo.com/main" }}?q={{ "param" }}">`,694 output: `<source src="http://www.foo.com/main?q=param">`,695 err: ``,696 },697 {698 input: `<source src="j{{ "avascript:alert(1)" }}">`,699 output: ``,700 err: `action cannot be interpolated into the "src" URL attribute value of this "source" element: URL prefix "j" is unsafe; it might be interpreted as part of a scheme`,701 },702 {703 input: `<source src="javascript:{{ "alert(1)" }}">`,704 output: ``,705 err: `action cannot be interpolated into the "src" URL attribute value of this "source" element: URL prefix "javascript:" contains an unsafe scheme`,706 },707 {708 input: `<source src="{{ "http://www.foo.com/?q=hello\\.world" }}">`,709 output: `<source src="http://www.foo.com/?q=hello%5c.world">`,710 err: ``,711 },712 {713 input: `<source src=" {{ "not interpreted as a URL prefix" }}">`,714 output: ``,715 err: `action cannot be interpolated into the "src" URL attribute value of this "source" element: URL prefix " " contains whitespace or control characters`,716 },717 {718 input: `<source src="/path/{{ ".." }}/{{ "foo" }}?n1=v1">`,719 output: `<source src="/path/../foo?n1=v1">`,720 err: ``,721 },722 {723 input: `<source src="/foo?a=b{{range $k, $v := .QueryParams}}&{{$k}}={{$v}}{{end}}">`,724 output: `<source src="/foo?a=b&k1=v1&k2=v2&k3=v3">`,725 err: ``,726 },727 // Attribute value contexts that expect Style.728 {729 input: `<p style="{{ "width: 1em;height: 1em;" }}">foo</p>`,730 output: ``,731 err: `expected a safehtml.Style value`,732 },733 {734 input: `<p style="{{ makeStyleForTest "width: 1em;height: 1em;" }}">foo</p>`,735 output: `<p style="width: 1em;height: 1em;">foo</p>`,736 err: ``,737 },738 {739 input: `<p style="color:green; &{{ "gt;<script>alert(1);</script>" }}">foo</p>`,740 output: ``,741 err: `action cannot be interpolated into the "style" attribute value of this "p" element: prefix "color:green; &" ends with an incomplete HTML character reference; did you mean "&" instead of "&"?`,742 },743 // Element content contexts that expect StyleSheet.744 {745 input: `<style>{{ "P.special { color:red ; }" }}</style>`,746 output: ``,747 err: `expected a safehtml.StyleSheet value`,748 },749 {750 input: `<style>{{ makeStyleSheetForTest "P.special { color:red ; }" }}</style>`,751 output: `<style>P.special { color:red ; }</style>`,752 err: ``,753 },754 {755 input: `<style>// {{"cannot insert dynamic comment"}}</style>`,756 output: ``,757 err: `expected a safehtml.StyleSheet value`,758 },759 {760 input: `<style>/* </b{{"notParsedAsTagName"}} */</style>`,761 output: ``,762 err: `expected a safehtml.StyleSheet value`,763 },764 // Element content contexts that expect Script.765 {766 input: `<script>{{ "alert(1);" }}</script>`,767 output: ``,768 err: `expected a safehtml.Script value`,769 },770 {771 input: `<script>{{ makeScriptForTest "alert(1);" }}</script>`,772 output: `<script>alert(1);</script>`,773 err: ``,774 },775 {776 input: `<script>// {{"cannot insert dynamic comment"}}</script>`,777 output: ``,778 err: `expected a safehtml.Script value`,779 },780 // Attribute value contexts that expect enumerated string values.781 {782 input: `<a target="{{ "blah" }}">foo</a>`,783 output: ``,784 err: `expected one of the following strings: ["_blank" "_self"]`,785 },786 {787 input: `<a target="{{ "_blank" }}">foo</a>`,788 output: `<a target="_blank">foo</a>`,789 err: ``,790 },791 {792 input: `<a target="{{ "_self" }}">foo</a>`,793 output: `<a target="_self">foo</a>`,794 err: ``,795 },796 {797 input: `<a target="prefix{{ "_self" }}">foo</a>`,798 output: ``,799 err: `partial substitutions are disallowed in the "target" attribute value context of a "a" element`,800 },801 // Attribute value contexts that expect Identifiers.802 {803 input: `<p name="{{ "my-identifier" }}" id="{{ "my-identifier" }}">foo</p>`,804 output: ``,805 err: `expected a safehtml.Identifier value`,806 },807 {808 input: `<p name="{{ makeIdentifierForTest "my-identifier" }}" id="{{ makeIdentifierForTest "my-identifier" }}">foo</p>`,809 output: `<p name="my-identifier" id="my-identifier">foo</p>`,810 err: ``,811 },812 // Element content contexts that expect RCDATA.813 {814 input: `<textarea>{{ "</textarea><script>alert('pwned!');</script>" }}</textarea>`,815 output: `<textarea></textarea><script>alert('pwned!');</script></textarea>`,816 err: ``,817 },818 {819 input: `<title>{{ "</title><script>alert('pwned!');</script>" }}</title>`,820 output: `<title></title><script>alert('pwned!');</script></title>`,821 err: ``,822 },823 // data-* attributes values.824 {825 input: `<p data-foo="{{ "foo" }}" data-bar="{{ "b<a>r" }}">baz</p>`,826 output: `<p data-foo="foo" data-bar="b<a>r">baz</p>`,827 err: ``,828 },829 {830 input: `<p data-4badname="{{ "foo" }}">baz</p>`,831 output: ``,832 err: `actions must not occur in the "data-4badname" attribute value context of a "p" element`,833 },834 // Attribute sanitization contexts propagate correctly over conditionals.835 // Notice that the if and else branches are sanitized differently and correctly.836 {837 input: `<a {{if 1}}id="{{ "foo:bar" }}"{{else}}href="{{ "foo:bar" }}"{{end}}>foo</a>`,838 output: ``,839 err: `expected a safehtml.Identifier value`,840 },841 {842 input: `<a {{if 0}}id="{{ "foo:bar" }}"{{else}}href="{{ "foo:bar" }}"{{end}}>foo</a>`,843 output: `<a href="about:invalid#zGoSafez">foo</a>`,844 err: ``,845 },846 // Conditional valueless attribute name.847 {848 input: `<img class="{{"iconClass"}}"` +849 `{{if 1}} color="{{"<iconColor>"}}"{{end}}` +850 // Double quotes inside if/else.851 ` src=` +852 `{{if 1}}"/foo?{{"<iconPath>"}}"` +853 `{{else}}"images/cleardot.gif"{{end}}` +854 // Missing space before title, but it is not a855 // part of the src attribute.856 `{{if .T}}title="{{"<title>"}}"{{end}}` +857 // Quotes outside if/else.858 ` alt="` +859 `{{if .T}}{{"<alt>"}}` +860 `{{else}}{{if .F}}{{"<title>"}}{{end}}` +861 `{{end}}"` +862 `>`,863 output: `<img class="iconClass" color="<iconColor>" src="/foo?%3ciconPath%3e"title="<title>" alt="<alt>">`,864 err: ``,865 },866 } {867 tmpl := Must(New("").Funcs(testConversionFuncs).Parse(stringConstant(test.input)))868 var b bytes.Buffer869 err := tmpl.Execute(&b, data)870 if test.err != "" {871 if err == nil {872 t.Errorf("%s : expected error", test.input)873 continue874 }875 if got := err.Error(); !strings.Contains(got, test.err) {876 t.Errorf("%s : error\n\t%q\ndoes not contain expected string\n\t%q", test.input, got, test.err)877 }878 continue879 }880 if test.err == "" && err != nil {881 t.Errorf("%s : template execution failed:\n%s", test.input, err)882 continue883 }884 if want, got := test.output, b.String(); want != got {885 t.Errorf("%s : escaped output: got\n\t%s\nwant\n\t%s", test.input, got, want)886 continue887 }888 }889}890func TestConditionalURLPrefixError(t *testing.T) {891 data := struct {892 B []string893 C, D bool894 URLSuffix string895 }{896 B: []string{"foo", "bar"},897 C: false,898 D: true,899 URLSuffix: "suffix",900 }901 for _, test := range [...]struct {902 input, want string903 }{904 // Conditonal URL prefix in attribute value contexts that expect URLs.905 {906 `<q cite="{{if .C}}mailto:{{end}}{{ .URLSuffix }}">foo</q>`,907 `actions must not occur after an ambiguous URL prefix`,908 },909 {910 `<q cite="{{if .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">foo</q>`,911 `actions must not occur after an ambiguous URL prefix`,912 },913 {914 `<q cite="{{if .C}}mailto{{else}}javascript{{end}}:{{ .URLSuffix }}">foo</q>`,915 `actions must not occur after an ambiguous URL prefix`,916 },917 {918 `<q cite="{{if .C}}mailto:{{else if .D}}javascript:{{else}}tel:{{end}}{{ .URLSuffix }}">foo</q>`,919 `actions must not occur after an ambiguous URL prefix`,920 },921 {922 `<q cite="{{range .B}}mailto:{{end}}{{ .URLSuffix }}">foo</q>`,923 `actions must not occur after an ambiguous URL prefix`,924 },925 {926 `<q cite="{{range .B}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">foo</q>`,927 `actions must not occur after an ambiguous URL prefix`,928 },929 {930 `<q cite="{{with .C}}mailto:{{end}}{{ .URLSuffix }}">foo</q>`,931 `actions must not occur after an ambiguous URL prefix`,932 },933 {934 `<q cite="{{with .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">foo</q>`,935 `actions must not occur after an ambiguous URL prefix`,936 },937 // Conditonal URL prefix in attribute value contexts that expect TrustedResourceURLs.938 {939 `<link href="{{if .C}}mailto:{{end}}{{ .URLSuffix }}">`,940 `actions must not occur after an ambiguous URL prefix`,941 },942 {943 `<link href="{{if .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,944 `actions must not occur after an ambiguous URL prefix`,945 },946 {947 `<link href="{{if .C}}mailto{{else}}javascript{{end}}:{{ .URLSuffix }}">`,948 `actions must not occur after an ambiguous URL prefix`,949 },950 {951 `<link href="{{if .C}}mailto:{{else if .D}}javascript:{{else}}tel:{{end}}{{ .URLSuffix }}">`,952 `actions must not occur after an ambiguous URL prefix`,953 },954 {955 `<link href="{{range .B}}mailto:{{end}}{{ .URLSuffix }}">`,956 `actions must not occur after an ambiguous URL prefix`,957 },958 {959 `<link href="{{range .B}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,960 `actions must not occur after an ambiguous URL prefix`,961 },962 {963 `<link href="{{with .C}}mailto:{{end}}{{ .URLSuffix }}">`,964 `actions must not occur after an ambiguous URL prefix`,965 },966 {967 `<link href="{{with .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,968 `actions must not occur after an ambiguous URL prefix`,969 },970 // Conditonal URL prefix in attribute value contexts that expect URLs or TrustedResourceURLs.971 {972 `<source src="{{if .C}}mailto:{{end}}{{ .URLSuffix }}">`,973 `actions must not occur after an ambiguous URL prefix`,974 },975 {976 `<source src="{{if .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,977 `actions must not occur after an ambiguous URL prefix`,978 },979 {980 `<source src="{{if .C}}mailto{{else}}javascript{{end}}:{{ .URLSuffix }}">`,981 `actions must not occur after an ambiguous URL prefix`,982 },983 {984 `<source src="{{if .C}}mailto:{{else if .D}}javascript:{{else}}tel:{{end}}{{ .URLSuffix }}">`,985 `actions must not occur after an ambiguous URL prefix`,986 },987 {988 `<source src="{{range .B}}mailto:{{end}}{{ .URLSuffix }}">`,989 `actions must not occur after an ambiguous URL prefix`,990 },991 {992 `<source src="{{range .B}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,993 `actions must not occur after an ambiguous URL prefix`,994 },995 {996 `<source src="{{with .C}}mailto:{{end}}{{ .URLSuffix }}">`,997 `actions must not occur after an ambiguous URL prefix`,998 },999 {1000 `<source src="{{with .C}}mailto:{{else}}javascript:{{end}}{{ .URLSuffix }}">`,1001 `actions must not occur after an ambiguous URL prefix`,1002 },1003 } {1004 tmpl := Must(New(test.input).Parse(stringConstant(test.input)))1005 var b bytes.Buffer1006 err := tmpl.Execute(&b, data)1007 if err == nil {1008 t.Errorf("expected an error for template %s", test.input)1009 continue1010 }1011 if got := err.Error(); !strings.Contains(got, test.want) {1012 t.Errorf("got error:\n\t%s\nwant:\n\t%s", got, test.want)1013 }1014 }1015}1016func TestValidateDoesNotEndsWithCharRefPrefix(t *testing.T) {1017 const wantErr = `ends with an incomplete HTML character reference; did you mean "&" instead of "&"?`1018 for _, test := range [...]struct {1019 in string1020 valid bool1021 }{1022 // Incomplete HTML character escape sequences.1023 {`&`, false},1024 {`javascript&`, false},1025 {`javascript&c`, false},1026 {`javascript&colon`, false},1027 {`javascript&blk1`, false},1028 {`javascript&#`, false},1029 {`javascript`, false},1030 {`javascript&#x`, false},1031 {`javascript
`, false},1032 {`javascript
`, false},1033 {`javascript`, false},1034 // Invalid HTML character references.1035 {`javascript&x3A;`, true},1036 {`javascript&x3a;`, true},1037 {`javascript&X3A;`, true},1038 {`javascript&X3a;`, true},1039 // Complete HTML character references.1040 {`javascript:`, true},1041 {`javascript:`, true},1042 } {1043 err := validateDoesNotEndsWithCharRefPrefix(test.in)1044 switch {1045 case err != nil:1046 if test.valid {1047 t.Errorf("validateDoesNotEndsWithCharRefPrefix(%q) failed: %s", test.in, err)1048 } else if !strings.Contains(err.Error(), wantErr) {1049 t.Errorf("validateDoesNotEndsWithCharRefPrefix(%q) error\n\t%s\ndoes not contain expected string\n\t%s", test.in, err.Error(), wantErr)1050 }1051 case !test.valid:1052 t.Errorf("validateDoesNotEndsWithCharRefPrefix(%q) succeeded unexpectedly", test.in)1053 }1054 }1055}1056func TestDataAttributeNamePattern(t *testing.T) {1057 for _, test := range [...]struct {1058 in string1059 want bool1060 }{1061 {`data-a`, true},1062 {`data-foo`, true},1063 {`data-foo-bar`, true},1064 {`data-f0o-b4r`, true},1065 {`data-_foo`, true},1066 // Does not begin with "data-".1067 {`data`, false},1068 {`foo`, false},1069 // No characters after hyphen.1070 {`data-`, false},1071 // Suffix starts with a digit.1072 {`data-4oo`, false},1073 // Contains ACSII upper alphas.1074 // Note: this test case isn't strictly necessary, since sanitizerForContext is given1075 // lower-case attribute names.1076 {`data-Foo`, false},1077 // Contains colon characters.1078 {`data-foo:bar`, false},1079 // Contains unicode characters that are allowed in XML names1080 // (https://www.w3.org/TR/xml/#NT-Name), but conservatively rejected1081 // by our regexp pattern.1082 {"data-\u037Fbar", false},1083 {"data-fo\u0300", false},1084 } {1085 if got := dataAttributeNamePattern.MatchString(test.in); got != test.want {1086 t.Errorf("dataAttributeNamePattern.MatchString(%q) = %t", test.in, got)1087 }1088 }1089}1090const testSanitizationLogicWant = `cannot escape action {{.}}: unquoted attribute values disallowed`1091// TestSanitizationLogic ensures that the underlying html/template sanitization logic is1092// replaced by the safehtml/template sanitization logic no matter how the template is parsed1093// or executed.1094func TestSanitizationLogic(t *testing.T) {1095 // This template will be accepted by html/template but not by safehtml/template1096 // since the latter does not allow data to be substituted into unquoted attribute1097 // value contexts.1098 const templateText = `<a href={{.}}>unquoted href attribute value</a>`1099 // Create temp file containing the template text for constructors that parse templates1100 // from files.1101 tmpfile, err := ioutil.TempFile("", "path")1102 if err != nil {1103 t.Fatal(err)1104 }1105 defer os.Remove(tmpfile.Name())1106 if _, err := tmpfile.WriteString(templateText); err != nil {1107 t.Fatal(err)1108 }1109 filename := stringConstant(tmpfile.Name())1110 templateName := filepath.Base(tmpfile.Name())1111 for _, test := range [...]struct {1112 parseFuncName string1113 tmpl *Template1114 }{1115 {"Parse", Must(New(templateName).Parse(templateText))},1116 {"ParseFromTrustedTemplate", Must(New(templateName).ParseFromTrustedTemplate(MakeTrustedTemplate(templateText)))},1117 {"ParseFiles (method)", Must(New(templateName).ParseFiles(filename))},1118 {"ParseFiles (function)", Must(ParseFiles(filename))},1119 {"ParseFilesFromTrustedSources (method)", Must(New(templateName).ParseFilesFromTrustedSources(TrustedSourceFromConstant(filename)))},1120 {"ParseFilesFromTrustedSources (function)", Must(ParseFilesFromTrustedSources(TrustedSourceFromConstant(filename)))},1121 {"ParseGlob (method)", Must(New(templateName).ParseGlob(filename))},1122 {"ParseGlob (function)", Must(ParseGlob(filename))},1123 {"ParseGlobFromTrustedSource (method)", Must(New(templateName).ParseGlobFromTrustedSource(TrustedSourceFromConstant(filename)))},1124 {"ParseGlobFromTrustedSource (function)", Must(ParseGlobFromTrustedSource(TrustedSourceFromConstant(filename)))},1125 } {1126 var b bytes.Buffer1127 err := test.tmpl.Execute(&b, nil)1128 testSanitizationLogicCheckError(t, err, test.parseFuncName, "Execute")1129 _, err = test.tmpl.ExecuteToHTML(nil)1130 testSanitizationLogicCheckError(t, err, test.parseFuncName, "ExecuteToHTML")1131 err = test.tmpl.ExecuteTemplate(&b, templateName, nil)1132 testSanitizationLogicCheckError(t, err, test.parseFuncName, "ExecuteTemplate")1133 _, err = test.tmpl.ExecuteTemplateToHTML(templateName, nil)1134 testSanitizationLogicCheckError(t, err, test.parseFuncName, "ExecuteTemplateToHTML")1135 }1136}1137func testSanitizationLogicCheckError(t *testing.T, err error, parseFuncName, executeFuncName string) {1138 prefix := parseFuncName + ", " + executeFuncName1139 if err == nil {1140 t.Errorf("%s : expected execution error", prefix)1141 return1142 }1143 if got := err.Error(); !strings.Contains(got, testSanitizationLogicWant) {1144 t.Errorf("%s : the error message:\n\t%s\ndoes not contain:\n\t%s", prefix, got, testSanitizationLogicWant)1145 }1146}1147func TestCannotCallInternalSanitizers(t *testing.T) {1148 const templateName = "test"1149 // Programmatically generate templates that call each sanitizer function in the internal1150 // function map.1151 for sanitizerName := range funcs {1152 tmplText := `{{ "foo" | ` + sanitizerName + ` }}`1153 _, err := New(templateName).Parse(stringConstant(tmplText))1154 if err == nil {1155 t.Errorf("expected error parsing template which calls internal sanitizer %q", sanitizerName)1156 }1157 }1158}1159func TestExecuteErrors(t *testing.T) {1160 for _, test := range [...]struct {1161 desc string1162 tmpl stringConstant1163 data interface{}1164 want string1165 fullMatch bool1166 }{1167 {1168 desc: `invalid template`,1169 tmpl: `{{template "foo"}}`,1170 want: `no such template "foo"`,1171 },1172 {1173 desc: `missing '"' after recursive call`,1174 tmpl: `<select size="{{template "y"}}></select>` +1175 `{{define "y"}}{{if .Tail}}{{template "y" .Tail}}{{end}}3"{{end}}`,1176 want: `cannot compute output context for template y$htmltemplate_StateAttr_DelimDoubleQuote_attrSize_elementSelect`,1177 },1178 {1179 desc: `element and attribute name confused`,1180 tmpl: `<a=foo>`,1181 want: `: expected space, attr name, or end of tag, but got "=foo>"`,1182 },1183 {1184 desc: `urlquery is disallowed if it is not the last command in the pipeline`,1185 tmpl: `Hello, {{. | urlquery | print}}!`,1186 want: `predefined escaper "urlquery" disallowed in template`,1187 },1188 {1189 desc: `html is disallowed if it is not the last command in the pipeline`,1190 tmpl: `Hello, {{. | html | print}}!`,1191 want: `predefined escaper "html" disallowed in template`,1192 },1193 {1194 desc: `direct call to html is disallowed if it is not the last command in the pipeline`,1195 tmpl: `Hello, {{html . | print}}!`,1196 want: `predefined escaper "html" disallowed in template`,1197 },1198 {1199 desc: `html is disallowed in a pipeline that is in an unquoted attribute context, even if it is the last command in the pipeline`,1200 tmpl: `<div class={{. | html}}>Hello<div>`,1201 want: `predefined escaper "html" disallowed in template`,1202 },1203 {1204 desc: `html is allowed since it is the last command in the pipeline, but urlquery is not`,1205 tmpl: `Hello, {{. | urlquery | html}}!`,1206 want: `predefined escaper "urlquery" disallowed in template`,1207 },1208 {1209 desc: `unquoted attribute value disallowed`,1210 tmpl: `<a title={{ . }}>bar</a>`,1211 want: `unquoted attribute values disallowed`,1212 },1213 {1214 desc: `dynamic element name suffix 1`,1215 tmpl: `<a{{ "foo" }} title="foo">`,1216 want: `actions must not affect element or attribute names`,1217 },1218 {1219 desc: `dynamic element name suffix 2`,1220 tmpl: `<div{{template "y"}}>` +1221 // Illegal starting in stateTag but not in stateText.1222 `{{define "y"}} foo<b{{end}}`,1223 want: `"<" in attribute name: " foo<b"`,1224 },1225 {1226 desc: `dynamic whole attribute name 1`,1227 tmpl: `<area {{ "foo" }}>`,1228 want: `actions must not affect element or attribute names`,1229 },1230 {1231 desc: `dynamic whole attribute name 2`,1232 tmpl: `<area {{ "foo" }} title="foo">`,1233 want: `actions must not affect element or attribute names`,1234 },1235 {1236 desc: `dynamic whole attribute name 3`,1237 tmpl: `<area title="foo" {{ "foo" }}>`,1238 want: `actions must not affect element or attribute names`,1239 },1240 {1241 desc: `dynamic whole attribute name 4`,1242 tmpl: `<area {{ "foo" }}="foo">`,1243 want: `actions must not affect element or attribute names`,1244 },1245 {1246 desc: `dynamic attribute name suffix`,1247 tmpl: `<area t{{ "foo" }}="foo">`,1248 want: `actions must not affect element or attribute names`,1249 },1250 {1251 desc: `dynamic attribute name prefix`,1252 tmpl: `<area {{ "foo" }}t="foo">`,1253 want: `actions must not affect element or attribute names`,1254 },1255 {1256 desc: `missing quote in the else branch`,1257 tmpl: `{{if .Cond}}<a href="foo">{{else}}<a href="bar>{{end}}`,1258 want: `{{if}} branches end in different contexts`,1259 },1260 // When we have a conditional element or attribute name suffix, the1261 // sanitizer only sees the name prefix when performing template sanitization.1262 // The prefix is very unlikely to be a whitelisted element or attribute name1263 // on its own, and will therefore be rejected.1264 {1265 desc: `conditional element name suffix`,1266 tmpl: `<me{{if 1}}ta{{else}}nuitem{{end}}>{{ "foo" }}`,1267 want: `actions must not occur in the element content context of a "me" element`,1268 },1269 {1270 desc: `conditional attribute name suffix`,1271 tmpl: `<area d{{if 1}}raggabl{{else}}ropzon{{end}}e="{{ "foo" }}">`,1272 want: `actions must not occur in the "d" attribute value context of a "area" element`,1273 },1274 {1275 desc: `if = non-whitelisted element, else = HTML, safehtml/template conditonal branch error`,1276 tmpl: `{{if 0}}<object>{{end}}{{ "hello" }}`,1277 want: `conditional branch with element "object" results in sanitization error: ` +1278 `actions must not occur in the element content context of a "object" element`,1279 },1280 {1281 desc: `if = Script, else = HTML, html/template conditonal branch error`,1282 tmpl: `{{if 0}}<script>{{end}}{{ "hello" }}`,1283 want: `branches end in different contexts`,1284 },1285 {1286 desc: `if = Script, else = HTML, safehtml/template conditonal branch error`,1287 tmpl: `{{if 0}}<script{{else}}<span{{end}}>{{ "hello" }}`,1288 want: `conditional branches end in different element content sanitization contexts: ` +1289 `element "script" has sanitization context "Script", ` +1290 `element "span" has sanitization context "HTML"`,1291 },1292 {1293 desc: `if = Script, else = HTML, html/template conditonal branch error`,1294 tmpl: `{{if 0}}<script>{{else}}<span>{{end}}{{ "hello" }}`,1295 want: `branches end in different contexts`,1296 },1297 {1298 desc: `if = Script, else if = HTML, else = HTML, html/template conditonal branch error`,1299 tmpl: `{{if 0}}<script>{{else if 1}}<span>{{else}}<b>{{end}}{{ "hello" }}`,1300 want: `branches end in different contexts`,1301 },1302 {1303 desc: `range = non-whitelisted element, else = HTML, safehtml/template conditonal branch error`,1304 tmpl: `{{range .}}<object>{{end}}{{ "hello" }}`,1305 data: []string{"foo", "bar"},1306 want: `conditional branch with element "object" results in sanitization error: ` +1307 `actions must not occur in the element content context of a "object" element`,1308 },1309 {1310 desc: `range = Script, else = HTML, html/template conditonal branch error`,1311 tmpl: `{{range .}}<script>{{end}}{{ "hello" }}`,1312 data: []string{"foo", "bar"},1313 want: `branches end in different contexts`,1314 },1315 {1316 desc: `range = Script, else = HTML, html/template conditonal branch error`,1317 tmpl: `{{range .}}<script>{{else}}<area>{{end}}{{ "hello" }}`,1318 data: []string{"foo", "bar"},1319 want: `branches end in different contexts`,1320 },1321 {1322 desc: `with = non-whitelisted element, else = HTML, safehtml/template conditonal branch error`,1323 tmpl: `{{with 0}}<object>{{end}}{{ "hello" }}`,1324 want: `conditional branch with element "object" results in sanitization error: ` +1325 `actions must not occur in the element content context of a "object" element`,1326 },1327 {1328 desc: `with = Script, else = HTML, html/template conditonal branch error`,1329 tmpl: `{{with 0}}<script>{{end}}{{ "hello" }}`,1330 want: `branches end in different contexts`,1331 },1332 {1333 desc: `with = Script, else = HTML, safehtml/template conditonal branch error`,1334 tmpl: `{{with 0}}<script{{else}}<span{{end}}>{{ "hello" }}`,1335 want: `conditional branches end in different element content sanitization contexts: ` +1336 `element "script" has sanitization context "Script", ` +1337 `element "span" has sanitization context "HTML"`,1338 },1339 {1340 desc: `with = Script, else = HTML, html/template conditonal branch error`,1341 tmpl: `{{with 0}}<script>{{else}}<span>{{end}}{{ "hello" }}`,1342 want: `branches end in different contexts`,1343 },1344 {1345 desc: `if = non-whitelisted attribute, else = no sanitization, safehtml/template conditonal branch error`,1346 tmpl: `<p {{if 0}}customattr{{else}}class{{end}}="{{ "hello" }}">`,1347 want: `conditional branch with {element="p", attribute="customattr"} results in sanitization error: ` +1348 `actions must not occur in the "customattr" attribute value context of a "p" element`,1349 },1350 {1351 desc: `if = TrustedResourceURLOrURL, else = TrustedResourceURL, safehtml/template conditonal branch error`,1352 tmpl: `{{if 0}}<img{{else}}<track{{end}} src="{{ "hello" }}">`,1353 want: `conditional branches end in different attribute value sanitization contexts: ` +1354 `{element="img", attribute="src"} has sanitization context "TrustedResourceURLOrURL", ` +1355 `{element="track", attribute="src"} has sanitization context "TrustedResourceURL"`,1356 },1357 {1358 desc: `if = TrustedResourceURLOrURL, else if = TrustedResourceURLOrURL, else = TrustedResourceURL, html/template conditonal branch error`,1359 tmpl: `{{if 0}}<img{{else if 1}}<audio{{else}}<track{{end}} src="{{ "hello" }}">`,1360 want: `conditional branches end in different attribute value sanitization contexts: ` +1361 `{element="img", attribute="src"} has sanitization context "TrustedResourceURLOrURL", ` +1362 `{element="track", attribute="src"} has sanitization context "TrustedResourceURL"`,1363 },1364 {1365 desc: `if = TrustedResourceURLOrURL, else = Identifier, safehtml/template conditonal branch error`,1366 tmpl: `<a {{if 0}}href{{else}}id{{end}}="{{ "hello" }}">`,1367 want: `conditional branches end in different attribute value sanitization contexts: ` +1368 `{element="a", attribute="href"} has sanitization context "TrustedResourceURLOrURL", ` +1369 `{element="a", attribute="id"} has sanitization context "Identifier"`,1370 },1371 {1372 desc: `if = TrustedResourceURLOrURL, else if = Identifier, else = TargetEnum, safehtml/template conditonal branch error`,1373 tmpl: `<a {{if 0}}href{{else if .D}}id{{else}}target{{end}}="{{ "hello" }}">`,1374 want: `conditional branches end in different attribute value sanitization contexts: ` +1375 `{element="a", attribute="href"} has sanitization context "TrustedResourceURLOrURL", ` +1376 `{element="a", attribute="target"} has sanitization context "TargetEnum"`,1377 },1378 {1379 desc: `range = non-whitelisted attribute, else = no sanitization, safehtml/template conditonal branch error`,1380 tmpl: `<p {{range .}}customattr{{else}}class{{end}}="{{ "hello" }}">`,1381 data: []string{"foo", "bar"},1382 want: `conditional branch with {element="p", attribute="customattr"} results in sanitization error: ` +1383 `actions must not occur in the "customattr" attribute value context of a "p" element`,1384 },1385 {1386 desc: `range = TrustedResourceURLOrURL, else = Identifier, safehtml/template conditonal branch error`,1387 tmpl: `<a {{range .}}href{{else}}id{{end}}="{{ "hello" }}">`,1388 data: []string{"foo", "bar"},1389 want: `conditional branches end in different attribute value sanitization contexts: ` +1390 `{element="a", attribute="href"} has sanitization context "TrustedResourceURLOrURL", ` +1391 `{element="a", attribute="id"} has sanitization context "Identifier"`,1392 },1393 {1394 desc: `with = non-whitelisted attribute, else = no sanitization, safehtml/template conditonal branch error`,1395 tmpl: `<p {{with 0}}customattr{{else}}class{{end}}="{{ "hello" }}">`,1396 want: `conditional branch with {element="p", attribute="customattr"} results in sanitization error: ` +1397 `actions must not occur in the "customattr" attribute value context of a "p" element`,1398 },1399 {1400 desc: `with = TrustedResourceURLOrURL, else = HTML, html/template conditonal branch error`,1401 tmpl: `{{with 0}}<img{{end}} src="{{ "hello" }}">`,1402 want: `branches end in different contexts`,1403 },1404 {1405 desc: `with = TrustedResourceURLOrURL, else = TrustedResourceURL, safehtml/template conditonal branch error`,1406 tmpl: `{{with 0}}<img{{else}}<track{{end}} src="{{ "hello" }}">`,1407 want: `conditional branches end in different attribute value sanitization contexts: ` +1408 `{element="img", attribute="src"} has sanitization context "TrustedResourceURLOrURL", ` +1409 `{element="track", attribute="src"} has sanitization context "TrustedResourceURL"`,1410 },1411 {1412 desc: `with = TrustedResourceURLOrURL, else = Identifier, safehtml/template conditonal branch error`,1413 tmpl: `<a {{with 0}}href{{else}}id{{end}}="{{ "hello" }}">`,1414 want: `conditional branches end in different attribute value sanitization contexts: ` +1415 `{element="a", attribute="href"} has sanitization context "TrustedResourceURLOrURL", ` +1416 `{element="a", attribute="id"} has sanitization context "Identifier"`,1417 },1418 {1419 desc: `non-whitelisted attributes disallowed`,1420 tmpl: `<option customattr="{{ . }}">`,1421 want: `actions must not occur in the "customattr" attribute value context of a "option" element`,1422 },1423 {1424 desc: `non-whitelisted element name disallowed 1`,1425 tmpl: `<imaginaryelement>{{ . }}</imaginaryelement>`,1426 want: `actions must not occur in the element content context of a "imaginaryelement" element`,1427 },1428 {1429 desc: `non-whitelisted element name disallowed 2`,1430 tmpl: `<base title="{{ . }}">`,1431 want: `actions must not occur in the "title" attribute value context of a "base" element`,1432 },1433 {1434 desc: `non-whitelisted element name disallowed 3`,1435 tmpl: `<meta title="{{ . }}">`,1436 want: `actions must not occur in the "title" attribute value context of a "meta" element`,1437 },1438 {1439 desc: `non-whitelisted element name disallowed 4`,1440 tmpl: `<object src="{{ . }}"></object>`,1441 want: `actions must not occur in the "src" attribute value context of a "object" element`,1442 },1443 {1444 desc: `non-whitelisted element name disallowed 5`,1445 tmpl: `<object>{{ . }}</object>`,1446 want: `actions must not occur in the element content context of a "object" element`,1447 },1448 {1449 desc: `conditional URL prefix error in URL attribute value sanitization context 1`,1450 tmpl: `<q cite="{{if 0}}mailto:{{end}}{{ "suffix" }}">foo</q>`,1451 want: `actions must not occur after an ambiguous URL prefix`,1452 },1453 {1454 desc: `conditional URL prefix error in URL attribute value sanitization context 2`,1455 tmpl: `<q cite="{{if 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">foo</q>`,1456 want: `actions must not occur after an ambiguous URL prefix`,1457 },1458 {1459 desc: `conditional URL prefix error in URL attribute value sanitization context 3`,1460 tmpl: `<q cite="{{if 0}}mailto{{else}}javascript{{end}}:{{ "suffix" }}">foo</q>`,1461 want: `actions must not occur after an ambiguous URL prefix`,1462 },1463 {1464 desc: `conditional URL prefix error in URL attribute value sanitization context 4`,1465 tmpl: `<q cite="{{if 0}}mailto:{{else if 1}}javascript:{{else}}tel:{{end}}{{ "suffix" }}">foo</q>`,1466 want: `actions must not occur after an ambiguous URL prefix`,1467 },1468 {1469 desc: `conditional URL prefix error in URL attribute value sanitization context 5`,1470 tmpl: `<q cite="{{range .B}}mailto:{{end}}{{ "suffix" }}">foo</q>`,1471 data: []string{"foo", "bar"},1472 want: `actions must not occur after an ambiguous URL prefix`,1473 },1474 {1475 desc: `conditional URL prefix error in URL attribute value sanitization context 6`,1476 tmpl: `<q cite="{{range .B}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">foo</q>`,1477 data: []string{"foo", "bar"},1478 want: `actions must not occur after an ambiguous URL prefix`,1479 },1480 {1481 desc: `conditional URL prefix error in URL attribute value sanitization context 7`,1482 tmpl: `<q cite="{{with 0}}mailto:{{end}}{{ "suffix" }}">foo</q>`,1483 want: `actions must not occur after an ambiguous URL prefix`,1484 },1485 {1486 desc: `conditional URL prefix error in URL attribute value sanitization context 8`,1487 tmpl: `<q cite="{{with 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">foo</q>`,1488 want: `actions must not occur after an ambiguous URL prefix`,1489 },1490 {1491 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 1`,1492 tmpl: `<link href="{{if 0}}mailto:{{end}}{{ "suffix" }}">`,1493 want: `actions must not occur after an ambiguous URL prefix`,1494 },1495 {1496 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 2`,1497 tmpl: `<link href="{{if 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1498 want: `actions must not occur after an ambiguous URL prefix`,1499 },1500 {1501 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 3`,1502 tmpl: `<link href="{{if 0}}mailto{{else}}javascript{{end}}:{{ "suffix" }}">`,1503 want: `actions must not occur after an ambiguous URL prefix`,1504 },1505 {1506 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 4`,1507 tmpl: `<link href="{{if 0}}mailto:{{else if 1}}javascript:{{else}}tel:{{end}}{{ "suffix" }}">`,1508 want: `actions must not occur after an ambiguous URL prefix`,1509 },1510 {1511 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 5`,1512 tmpl: `<link href="{{range .B}}mailto:{{end}}{{ "suffix" }}">`,1513 data: []string{"foo", "bar"},1514 want: `actions must not occur after an ambiguous URL prefix`,1515 },1516 {1517 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 6`,1518 tmpl: `<link href="{{range .B}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1519 data: []string{"foo", "bar"},1520 want: `actions must not occur after an ambiguous URL prefix`,1521 },1522 {1523 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 7`,1524 tmpl: `<link href="{{with 0}}mailto:{{end}}{{ "suffix" }}">`,1525 want: `actions must not occur after an ambiguous URL prefix`,1526 },1527 {1528 desc: `conditional URL prefix error in TrustedResourceURL attribute value sanitization context 8`,1529 tmpl: `<link href="{{with 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1530 want: `actions must not occur after an ambiguous URL prefix`,1531 },1532 {1533 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 1`,1534 tmpl: `<source src="{{if 0}}mailto:{{end}}{{ "suffix" }}">`,1535 want: `actions must not occur after an ambiguous URL prefix`,1536 },1537 {1538 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 2`,1539 tmpl: `<source src="{{if 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1540 want: `actions must not occur after an ambiguous URL prefix`,1541 },1542 {1543 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 3`,1544 tmpl: `<source src="{{if 0}}mailto{{else}}javascript{{end}}:{{ "suffix" }}">`,1545 want: `actions must not occur after an ambiguous URL prefix`,1546 },1547 {1548 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 4`,1549 tmpl: `<source src="{{if 0}}mailto:{{else if 1}}javascript:{{else}}tel:{{end}}{{ "suffix" }}">`,1550 want: `actions must not occur after an ambiguous URL prefix`,1551 },1552 {1553 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 5`,1554 tmpl: `<source src="{{range .B}}mailto:{{end}}{{ "suffix" }}">`,1555 data: []string{"foo", "bar"},1556 want: `actions must not occur after an ambiguous URL prefix`,1557 },1558 {1559 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 6`,1560 tmpl: `<source src="{{range .B}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1561 data: []string{"foo", "bar"},1562 want: `actions must not occur after an ambiguous URL prefix`,1563 },1564 {1565 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 7`,1566 tmpl: `<source src="{{with 0}}mailto:{{end}}{{ "suffix" }}">`,1567 want: `actions must not occur after an ambiguous URL prefix`,1568 },1569 {1570 desc: `conditional URL prefix error in TrustedResourceURLOrURL attribute value sanitization context 8`,1571 tmpl: `<source src="{{with 0}}mailto:{{else}}javascript:{{end}}{{ "suffix" }}">`,1572 want: `actions must not occur after an ambiguous URL prefix`,1573 },1574 {1575 desc: `error message reports accurate line number`,1576 tmpl: `<html>Line 11577Line 21578Line 31579Line 4<script>{{ "this will cause a run-time failure" }}</script>1580Line 51581Line 6</html>`,1582 want: `template: error message reports accurate line number:4:17: executing "error message reports accurate line number" at <_sanitizeScript>: error calling _sanitizeScript: expected a safehtml.Script value`,1583 fullMatch: true,1584 },1585 {1586 desc: `ends in non-text context 1`,1587 tmpl: `<a width=1 title={{"hello"}}`,1588 want: `ends in non-text context`,1589 },1590 {1591 desc: `ends in non-text context 2`,1592 tmpl: "<script>foo();",1593 want: `ends in non-text context`,1594 },1595 {1596 desc: `unquoted static attribute value 1`,1597 tmpl: `<input type=button value= 1+1=2>`,1598 want: `"=" in unquoted attr: "1+1=2"`,1599 },1600 {1601 desc: `unquoted static attribute value 2`,1602 tmpl: "<a class=`foo>",1603 want: "\"`\" in unquoted attr: \"`foo\"",1604 },1605 } {1606 tmpl := Must(New(test.desc).Parse(test.tmpl))1607 var b bytes.Buffer1608 err := tmpl.Execute(&b, test.data)1609 if err == nil {1610 t.Errorf("%s: expected an error", test.desc)1611 return1612 }1613 got := err.Error()1614 if test.fullMatch && got != test.want {1615 t.Errorf("%s: got error:\n\t%q\nwant:\n\t%q", test.desc, got, test.want)1616 return1617 }1618 if !test.fullMatch && !strings.Contains(got, test.want) {1619 t.Errorf("%s: error\n\t%q\ndoes not contain expected string\n\t%q", test.desc, got, test.want)1620 }1621 }1622}...
check-generic_test.go
Source:check-generic_test.go
1package htmltest2import (3 "path"4 "testing"5 "github.com/wjdp/htmltest/issues"6)7var genericTests = []struct {8 fixture string9 errorCount int10}{11 {"areaValid.html", 0},12 {"areaBroken.html", 1},13 {"areaBlank.html", 2},14 {"areaMissing.html", 0},15 {"audioValid.html", 0},16 {"audioBroken.html", 5},17 {"audioBlank.html", 5},18 {"audioMissing.html", 0},19 {"citeValid.html", 0},20 {"citeBroken.html", 4},21 {"citeBlank.html", 4},22 {"citeMissing.html", 0},23 {"embedValid.html", 0},24 {"embedBroken.html", 1},25 {"embedBlank.html", 2},26 {"embedMissing.html", 0},27 {"iframeValid.html", 0},28 {"iframeBroken.html", 1},29 {"iframeBrokenButIgnored.html", 0},30 {"iframeBlank.html", 2},31 {"iframeMissing.html", 0},32 {"inputSrcValid.html", 0},33 {"inputSrcBroken.html", 1},34 {"inputSrcBlank.html", 2},35 {"inputSrcMissing.html", 0},36 {"objectValid.html", 0},37 {"objectBroken.html", 2},38 {"objectBlank.html", 2},39 {"objectMissing.html", 0},40 {"videoValid.html", 0},41 {"videoBroken.html", 9},42 {"videoBlank.html", 9},43 {"videoMissing.html", 0},44}45func TestCheckGenericTable(t *testing.T) {46 for _, gt := range genericTests {47 hT := tTestFileOpts(path.Join("fixtures/generic", gt.fixture),48 map[string]interface{}{"VCREnable": true})49 c := hT.issueStore.Count(issues.LevelError)50 if c != gt.errorCount {51 t.Error("error count", c, "!=", gt.errorCount, "in", gt.fixture)52 hT.issueStore.DumpIssues(true)53 }54 }55}...
Cite
Using AI Code Generation
1import (2func main() {3 fmt.Println(html.EscapeString("This is <b>HTML</b>"))4}5import (6func main() {7 fmt.Println(html.UnescapeString("This is <b>HTML</b>"))8}9import (10func main() {11 fmt.Println(html.EscapeString("This is <b>HTML</b>"))12}13import (14func main() {15 fmt.Println(html.UnescapeString("This is <b>HTML</b>"))16}17import (18func main() {19 fmt.Println(html.EscapeString("This is <b>HTML</b>"))20}21import (22func main() {23 fmt.Println(html.UnescapeString("This is <b>HTML</b>"))24}25import (26func main() {27 fmt.Println(html.EscapeString("This is <b>HTML</b>"))28}29import (
Cite
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6 fmt.Println(html.Comment("This is a comment"))7}8import (9func main() {10 fmt.Println(html.Commentf("This is a %s", "comment"))11}12import (13func main() {14 fmt.Println(html.Format("A < B"))15}16import (17func main() {18 fmt.Println(html.FormatBytes([]byte("A < B")))19}20import (21func main() {22 fmt.Println(html.FormatFloat(123.456))23}24import (25func main() {26 fmt.Println(html.FormatInt(123))27}28import (29func main() {30 fmt.Println(html.FormatUint(123))31}32import (33func main() {34 fmt.Println(html.FormatBool(true))35}
Cite
Using AI Code Generation
1import (2func main() {3 fmt.Println(html.Cite("Hello, World!"))4}5import (6func main() {7 fmt.Println(html.Comment("Hello, World!"))8}9import (10func main() {11 fmt.Println(html.Commentf("Hello, %s!", "World"))12}13import (14func main() {15 fmt.Println(html.Format("Hello, <b>World</b>!"))16}17import (18func main() {19 fmt.Println(html.FormatBytes([]byte("Hello, <b>World</b>!")))20}21import (22func main() {23 fmt.Println(html.FormatHTML("Hello, <b>World</b>!"))24}25import (26func main() {27 fmt.Println(html.FormatHTMLBytes([]byte("Hello, <b>World</b>!")))28}29import (30func main() {31 html.FormatHTMLTo(&b, "Hello, <b>World</b>!")32 fmt.Println(b.String())33}
Cite
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6 fmt.Println(html.Code("Hello World"))7}8import (9func main() {10 fmt.Println(html.Data("Hello World"))11}12import (13func main() {14 fmt.Println(html.DataList("Hello World"))15}16import (17func main() {18 fmt.Println(html.Del("Hello World"))19}20import (21func main() {22 fmt.Println(html.Details("Hello World"))23}24import (25func main() {26 fmt.Println(html.Dialog("Hello World"))27}28import (29func main() {30 fmt.Println(html.Div("Hello World"))31}32import (33func main() {34 fmt.Println(html.Dfn("Hello World"))35}
Cite
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6 fmt.Println(html.Date())7}8import (9func main() {10 fmt.Println(html.EscapeString("hello <b>world</b>"))11}12hello <b>world</b>13import (14func main() {15 fmt.Println(html.Format("hello <b>world</b>"))16}17import (18func main() {19 fmt.Println(html.FormatBytes([]byte("hello <b>world</b>")))20}21import (22func main() {23 fmt.Println(html.FormatFloat(123.45))24}25import (26func main() {27 fmt.Println(html.FormatInt(123))28}29import (30func main() {31 fmt.Println(html.FormatUint(123))32}33import (
Cite
Using AI Code Generation
1import (2func main() {3 fmt.Println(html.Cite("Hello, world!"))4}5import (6func main() {7 fmt.Println(html.Cite("Hello, world!"))8}9import (10func main() {11 fmt.Println(html.Cite("Hello, world!"))12}13import (14func main() {15 fmt.Println(html.Cite("Hello, world!"))16}17import (18func main() {19 fmt.Println(html.Cite("Hello, world!"))20}21import (22func main() {23 fmt.Println(html.Cite("Hello, world!"))24}25import (26func main() {27 fmt.Println(html.Cite("Hello, world!"))28}29import (30func main() {31 fmt.Println(html.Cite("Hello, world!"))32}33import (34func main() {35 fmt.Println(html.Cite("Hello, world!"))36}
Cite
Using AI Code Generation
1import (2func main() {3 fmt.Println(html.Cite("Hello World"))4}5import (6func main() {7 fmt.Println(html.Command("Hello World"))8}9import (10func main() {11 fmt.Println(html.Datalist("Hello World"))12}13import (14func main() {15 fmt.Println(html.Details("Hello World"))16}17import (18func main() {19 fmt.Println(html.Dialog("Hello World"))20}21import (22func main() {23 fmt.Println(html.Dfn("Hello World"))24}25import (26func main() {27 fmt.Println(html.Div("Hello World"))28}29import (30func main() {31 fmt.Println(html.Dl("Hello World"))32}
Cite
Using AI Code Generation
1import (2func main() {3}4import (5func main() {6 fmt.Println(html.Date())7}8import (9func main() {10 fmt.Println(html.EscapeString("This is <b>HTML</b>"))11}12This is <b>HTML</b>13import (14func main() {15 fmt.Println(html.FormatFloat(3.141592, 'f', 2, 64))16}17import (18func main() {19 fmt.Println(html.FormatInt(42, 16))20}21import (22func main() {23 fmt.Println(html.FormatUint(42, 16))24}25import (26func main() {27 fmt.Println(html.JSString("alert('Hello, world!');"))28}29alert('Hello, world!');30import (31func main() {32 fmt.Println(html.JS("alert('Hello, world!');"))33}34alert('Hello, world!');
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!