Kommentarfunktion i ASP

Nu tänkte jag presentera min helt egna kommentarfunktion som jag gjort i ASP/VB. Jag försöker förklara lite övergripande vad som sker men kommer inte gå in på varenda detalj.

kommentarer.asp (formuläret)

Ett helt vanligt HTML-formulär där vi använder attributet name för att senare identifiera vilken uppgift som ska till vilket ställe i databasen.

<table width="550" align="left" border="0">
<form method="post" action="spara.asp?do=spara">
  <tr>
	<td colspan="3" width="550"><b>Rubrik:</b> (max 45 tecken)<br /><input maxlength="45" value="" name="rubrik" class="c_input_l" /></td>
  </tr>
  <tr>
	<td colspan="3" width="550"><b>Text:</b><br><textarea name="kommentar" class="c_textarea"></textarea>
	<p class="text_xs_nm">Följande HTML-taggar kan/får användas: <em>kursiv</em> <em></em> och <strong>fet</strong> <strong></strong></p></td>
  </tr>
  <tr>
	<td width="245" valign="top"><b>Namn:</b><br><input value="" name="namn" class="c_input" /></td>
	<td width="245" valign="top"><b>Hemsida:</b><br /><input value="http://www." name="hemsida" class="c_input" /></td>
  </tr>
  <tr>
	<td width="275" valign="top"><b>E-post:</b><br /><input value="" name="epost" class="c_input" />
	</td>
	<td width="275" valign="top"><b>Spamskydd:</b><br /><img src="grafik/captcha.jpg" class="ikon"> <input value="" name="spamprot" class="c_input_s2" /></td>
  </tr>
  <tr>
	<td colspan="3" width="550">
	<input type="submit" value="Posta kommentar" class="form_submit" />
	</td>
  </tr>
</form>
</table>

spara.asp

Funktionen för att spara kommentarerna hämtar captcha-koden och den aktuella tiden och lägger i variabler. De resterande uppgifterna lägger jag (slarvigt nog) inte i variabler, utan hämtas i samma stund som jag matar in upppgifterna i databasen.

Filen funktioner.asp inkluderas eftersom jag behöver funktionen FixaTecken som gör om citationstecken till två st ‘.

<%If Request.Querystring("do") = "spara" Then
	<!--#include file="includes/funktioner.asp"-->
	Set Conn = Server.CreateObject("ADODB.Connection")
	Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &Server.MapPath("databas\db.mdb")

	spamprotection	= Request.Form("spamprot")
	tid = FormatDateTime(Time, vbLongTime)

	If spamprotection = "D4gf68Z" Then
		SQL = "Insert Into comments (title,comment,datum,tid,namn,hemsida,epost) Values('" & FixaTecken(Request.Form("rubrik")) & "','" & FixaTecken(Request.Form("kommentar")) & "','" & date & "','" & tid & "','" & Request.Form("namn") & "','" & Request.Form("hemsida") & "','" & Request.Form("epost") & "')"
		Conn.Execute(SQL)

		Response.Redirect "http://www.doman.se/kommentarer.asp?next=1"
	Else
		Response.Redirect "http://www.doman.se/kommentarer.asp?next=1"
	End If

	RecSet.Close
	Conn.Close
	Set RecSet = Nothing
	Set Conn = Nothing
End If%>

komentarer.asp (visa kommentarer)

Här börjar jag med att inkludera funktioner.asp eftersom jag behöver funktionen VbCrLfToBreak. Den gör så att radbrytningar som skrivits in i databasen genererar ett radbyte i HTML (<br />).

ANTAL=”7″ anger att sju kommentarer ska visas per sida.

Jag har lagt en funktion för att bläddra mellan kommentarssidorna både ovanför och under de sju kommentarer som visas.

Jag kontrollerar även om fälten namn och hemsida är ifyllda. Om de innehåller något så skrivs de ut och om båda är ifyllda så läggs ett kommatecken till mellan namnet och URL:en till hemsidan.

<%

<!--#include file="includes/funktioner.asp"-->
ANTAL = "7"
Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &Server.MapPath("databas\db.mdb")
Set RecSet = Server.CreateObject("ADODB.RecordSet")

	Sidan = Request.QueryString("next")
	If Sidan = "" then
	   sida = 1
	Else
	   sida = Sidan
	End If 

	With RecSet
	   .CursorLocation = 3
	   .CacheSize = ANTAL
	End With

SQL = "SELECT * FROM comments ORDER BY datum DESC, tid DESC"
RecSet.Open SQL, Conn

	With RecSet
	  .MoveFirst
	  .PageSize = ANTAL
	  .AbsolutePage = sida
	End With

	Sidor =  RecSet.PageCount
	 x = 0

If Sidor > 1 Then%>
	<div class="contentrow_sidnr">
		<p>
		<%If (Int(sida)) <> 1 Then%>
		<a href="kommentarer.asp?next=<%=(Int(sida)-1)%>" class="intern">Framåt</a> |
		<%Else%><%End If%>

		<%For Sid = 1 To Sidor
			 If (Int(Sid)) = (Int(sida)) Then%>
		<%=Sid%><%Else%> <a href="kommentarer.asp?next=<%=Sid%>" class="intern"><%=Sid%></a> <%End If
		 Next%>

		<%If (Int(sida)) <> (Int(Sidor)) Then%>
		 | <a href="kommentarer.asp?next=<%=(Int(sida)+1)%>" class="intern">Bakåt</a>
		<%Else%><%End If%>
		</p>
	</div>
	<div style="float: left; width: 630px; border-bottom: 1px solid #FF4500; margin: 0px; padding: 0px;"></div>
<%End If%>

<%Do While Not RecSet.EOF And x < RecSet.PageSize%>

<div class="commentrow">
<%
titel = RecSet("title")
If titel <> "" Then%>
	<h2><%=RecSet("title")%></h2>
<%End If%>

	<%
	tid_a = RecSet("tid")
	tiden = FormatDateTime(tid_a, vbShortTime)
	%>

	<p class="komdatum" style="margin"><%=RecSet("datum")%> - <%=tiden%></p>
	<p class="text_medium"><%Response.Write(VbCrLfToBreak(RecSet("comment")))%></p>

	<%
	namn = RecSet("namn")
	hemsida = RecSet("hemsida")
	%>

	<%If namn <> "" Then%>
	<p class="text_s" style="font-style:italic;"><%=RecSet("namn")%>
	<%End If%>

	<%If namn <> "" AND hemsida <> "http://www." AND hemsida <> "" Then Response.Write ", "%>

	<%If hemsida <> "http://www." OR hemsida = "" Then%>
	<a href="<%=RecSet("hemsida")%>" target="_blank" rel="nofollow" class="extern"><%=RecSet("hemsida")%></a>
	<%Else
	End If%>
	</p>
</div>

<%x=x+1
RecSet.MoveNext
Loop

If Sidor > 1 Then%>
	<div class="contentrow_sidnr">
		<p>
		<%If (Int(sida)) <> 1 Then%>
		<a href="kommentarer.asp?next=<%=(Int(sida)-1)%>" class="intern">Framåt</a> |
		<%Else%><%End If%>

		<%For Sid = 1 To Sidor
			 If (Int(Sid)) = (Int(sida)) Then%>
		<%=Sid%><%Else%> <a href="kommentarer.asp?next=<%=Sid%>" class="intern"><%=Sid%></a> <%End If
		 Next%>

		<%If (Int(sida)) <> (Int(Sidor)) Then%>
		 | <a href="kommentarer.asp?next=<%=(Int(sida)+1)%>" class="intern">Bakåt</a>
		<%Else%><%End If%>
		</p>
	</div>
<%End If%>
<%RecSet.Close
Conn.Close
Set RecSet = Nothing
Set Conn = Nothing%>

funktioner.asp

Function FixaTecken(str)
	FixaTecken  = Replace(Trim(str),"'","''")
End function

Function VbCrLfToBreak(byVal str)
	If IsNull(str) Then str = ""
	VbCrLfToBreak = Replace(str,vbCrLf,"<br />")
End Function

Hoppas allt blev rätt nu. Kanske hjälper detta någon som fortfarande kodar klassisk ASP.

Redirecta obefintliga sidor i ASP

På en av mina sajter har jag märkt att Google har indexerat sidor som egentligen inte finns. De består bara av sajtens ”skelett”, d.v.s. header, meny och högerkolumn, medan innehållsdelen saknas. Detta problem uppkommer då jag använder mig av s.k. QueryStrings i ASP, där varje sidas innehållsdel väljs beroende på vilken QueryString som anropas i URL:en (sida.asp?page=sida). Det blir dock endast synligt om man råkar länka till en QueryString som inte har något innehåll, vilket jag alltså varit slarvig och gjort.

För att få bort den ”tomma” sidan från Google har jag därför gjort en 301 Permanent Redirect från den felaktiga sidan/QueryStringen till den korrekta adressen. Det ser ut såhär i ASP:

<%@ Language=VBScript %>
<%
aktuellQS = Request.Querystring

If aktuellQS = "page=felaktig-querystring" Then
    Response.Status = "301 Moved Permanently"
    Response.AddHeader "Location", "http://www.doman.se/sidan.asp?page=korrekt-querystring"
    Response.End
End If
%>

Koden läggs högst upp i den ASP-fil som innehåller den felaktigt indexerade QueryStringen.

Jag tycker det är nödvändigt att få bort innehållslösa sidor från Googles index eftersom de just inte innehåller någonting. I mitt fall så syns ju ändå sajtens navigering, vilket man kan tycka är bra eftersom besökarna då kan klicka sig vidare. Jag tror dock att man tjänar på att hjälpa Google att bara indexera de sidor som faktiskt har ett innehåll. Dessutom så skickar man ju över den eventuella styrka den tomma sidan har till en sida som faktiskt har ett innehåll.

PHP- och ASP-länkar med ID

Jag har tidigare varit negativ till länkar som går via redirect-script och nu har jag lite mer på detta ämne. För att få ut mest av en inlänk till din sajt ska den vara skriven i ren HTML. Google följer tydligen sedan en tid länkar som går genom ASP-/PHP-redirects eller JavaScript. Problemet är att denna typ av länkar med största säkerhet har ett betydligt lägre värde, och bör således undvikas.

Har du länkar som du vill föra klickstatistik över, men ändå ge de länkade sidorna bra länkar så kan du använda dig av JavaScript för att räkna klick. Vill du hämta URL:er ur en databas med ASP eller PHP så går även det bra så länge du skriver ut dem i href=””. Problemet är inte att man använder något av dessa språk utan vilken länk man stoppar in i href.  Skriver du href=”inc/redirect.asp?id=3298″ så blir det en intern länk på din sajt. Besökaren som klickar på den märker troligtvis inget eftersom redirecten går lika snabbt som om länken pekat mot den länkade sajten från först början.

Exempel på hur du kan göra en ”bra” länk med ASP:
<a href=”<%=RecSet(”url”)%>” target=”blank”><%=RecSet(”titel”)%></a>

Som ger följande HTML-kod:
<a href=”http://www.runars-korgossar.se” target=”blank”>Runar’s körgossar</a>

Mer läsvärt hittar du här:
http://www.seo-guide.se/lank…de-varderas (Under rubrik 11)
http://www.seo-forum.se/inf…ummer.html

Mer Permanent Redirect i ASP

Jag har tidigare skrivit hur man gör en enkel 301-redirect från domän.se till www.domän.se. Nu har jag börjat använda nedanstående kod för att automatiskt kunna redirecta speciella sidor till adressen som inkluderar www. Placera koden längst upp på alla ASP-sidor du vill använda Permanent Redirect på.

<%@ Language=VBScript %>
<%
aktuellsida = Request.ServerVariables("URL")
aktuellQS = "?" & Request.Querystring

If ((Request.ServerVariables("SERVER_NAME")) = "doman.se") Then
    Response.Status = "301 Moved Permanently"
    Response.AddHeader "Location", "http://www.doman.se" & aktuellsida & aktuellQS
    Response.End
End If
%>

Variabeln ”aktuellsida” visas i denna färg, och ”aktuellQS” i denna färg i URL:en nedan.

http://www.doman.se/sida.asp?page=undersida

Unika Title-taggar med ASP

Ur SEO-synpunkt är det viktigt att ha unika Title-taggar för varje sida på din sajt, men det är även viktigt ur ett användarperspektiv. Med unika Title-taggar vit besökaren lätt vilken sida han/hon befinner sig på och var i sidhierarkin. För sökmotorernas del är Title-taggen en viktig källa till sökord som är relevanta för den aktuella sidan.

Här kommer jag visa både hur du skapar automatiskt genererade och manuellt ändringsbara Title-taggar om du använder flera QueryStrings på samma ASP-sida.

Manuellt med olika QueryStrings:

<html>
<head>
<meta http-equiv=”content-
type” content=”text/html; charset=utf-8″>
<meta name=”language” content=”sv”>
<link href=”style.css” type=”text/css” rel=”stylesheet”>

<%If Request.Querystring(”page”) = ”” Then%>
<title>Sajten.se – Startsidan på sajten.se</title>
<%End If%>
<%If Request.Querystring(”page”) = ”kontakta” Then%>

<title>
Sajten.se – Kontakta oss</title>
<%End If%>
</head>
….

Automatiskt genererade från databas:

<html>
<head>
<meta http-equiv=”content-
type” content=”text/html; charset=utf-8″>
<meta name=”language” content=”sv”>
<link href=”style.css” type=”text/css” rel=”stylesheet”>

<%
Set Conn = Server.CreateObject(”ADODB.Connection”)
Conn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &Server.MapPath(”d_bas\d_bas.mdb”)
Set RecSet = Conn.Execute(”SELECT * FROM en_tabell WHERE pageID=”& Request.Querystring(”page”))
%>

<title>Sajten.se<%=RecSet(”avdelning”)%><%=RecSet(”sidans_titel”)%></title>
<%
Conn.Close
End If
%>

</head>
….

Denna kod är från mina egna sajter och ändrad för att passa som exempel. Det kan hända att den inte fungerar klockrent, men jag hoppas att den ändå hjälper er på traven. För att att den automatiskt genererade Title-taggen ska fungera måste självklart informationen finnas tillgänglig i en databas.

Skriv till Access-databas med ASP

Tänkte nu göra en liten guide till hur man enkelt skriver information från ett formulär till en Access-databas i ASP. I detta exempel är det en kommentarfunktion från en av mina sajter som får agera exempel. Först börjar vi med att skapa formuläret i HTML, ni får ursäkta den omoderna tabellösningen utan CSS jag använder här. För att göra det snyggare föreslår jag att du sätter en class på alla input och bilder för att styla dem i en extern CSS-fil.

<table width=”550″ align=”left” border=”0″>
<form method=”post” action=”
?do=spara”>
<tr>
<td colspan=”3″ width=”550″><b>Rubrik:</b> (max 45 tecken)<br><input maxlength=”45″ name=”rubrik”></td>
</tr>
<tr>
<td colspan=”3″ width=”550″><b>Text:</b><br><textarea name=”comment”></textarea></td>
</tr>
<tr>
<td width=”245″ valign=”top”><b>Namn:</b><br><input value=”” name=”namn”></td>
<td width=”245″ valign=”top”><b>Hemsida:</b><br><input value=”http://www.” name=”hemsida” ></td>
</tr>
<tr>
<td width=”275″ valign=”top”><b>E-post:</b><br><input value=”” name=”epost”>
</td>
<td width=”275″ valign=”top”><b>Spamskydd:</b><br><img src=”grafik/kod2.jpg”><input value=”” name=”spamprot”></td>
</tr>
<tr>
<td colspan=”3″ width=”550″>
<input type=”submit” value=”Posta kommentar”>
</td>
</tr>
</form>
</table>

När formulärt är färdigt ska vi skriva ASP-koden som hämtar informationen från formuläret, lägger dem i variabler och sedan matar in dem på rätt plats i databasen. Ursäkta att koden är lite slarvigt skriven med en blandning av engelska och svenska.

<%
If Request.Querystring(”do”) = ”spara” Then
Set Conn = Server.CreateObject(”ADODB.Connection”)
Conn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &Server.MapPath(”databas\db.mdb”)spamprotection = Request.Form(”spamprot”)

If spamprotection = ”34$LkT” Then
SQL = ”Insert Into comments (title,comment,datum,namn,hemsida,epost) Values(‘” & Request.Form(”rubrik”) & ”‘,'” & Request.Form(”comment”) & ”‘,'” & date & ”‘,'” & Request.Form(”namn”) & ”‘,'” & Request.Form(”hemsida”) & ”‘,'” & Request.Form(”epost”) & ”‘)”
Conn.Execute(SQL)
RecSet.Close
Conn.Close
Set RecSet = Nothing
Set Conn = Nothing
Response.Redirect ”kommentarer.asp”
Else
Response.Redirect ”kommentarer.asp”
End If
End If
%>

Spamskydda dina formulär

Tidigare har jag skrivit ett inlägg där jag förklarar hur man skapar ett spamskydd i ASP. Det går ut på att låta besökaren upprepa tecken och siffror som syns i en bild, s.k captcha. Denna metod känner ni säkert igen från alla möjliga webbplatser.

Robert Falkén kommenterade inlägget och gav mig en alternativ metod för att förhindra spamrobotar att posta information via formulär. Han skapar helt enkelt en dold input som döps till något som lätt fångar spamrobotarnas intresse, t.ex. ”link” eller ”url”. Eftersom detta formulärfält är dolt för vanliga besökare så kommer det inte fyllas i av någon utom spamrobotar. Därefter kodar man en enkel funktion som kollar av om fältet är ifyllt eller ej. Är det ifyllt så avbryts postningen av formuläret. Ungefär som i det här exemplet:

<%
spamskydd = Request.Form(”url”)
If spamskydd <> ”” Then
Response.Redirect ”formularsida.asp”
Else
‘Hämta alla fält och mata in i databasen som vanligt
%>

Spamskydd i ASP

Här bjuder jag på ett enkelt spamskydd i ASP. Det har inte släppt igenom en enda spammning på de sajter jag använder det.

Formulär
<form method=”post” action=”?do=save”>
Spamskydd: <img src=”graphics/antispamcode.jpg”><input name=”spamprot”>
</form>

ASP (do=save)
<%If Request.Querystring(”do”) = ”save” Then
Set Conn = Server.CreateObject(”ADODB.Connection”)
Conn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &Server.MapPath(”database\database.mdb”)

spamprotection = Request.Form(”spamprot”)
If spamprotection = ”5Z3fk” Then
SQL = ”INSERT INTO comments (title,comment,postdate,postername,website) VALUES(‘” & Request.Form(”rubrik”) & ”‘,'” & Request.Form(”comment”) & ”‘,'” & date & ”‘,'” & Request.Form(”namn”) & ”‘,'” & Request.Form(”hemsida”) & ”‘)”
Conn.Execute(SQL)
Response.Redirect ”comments.asp”
Else
Response.Redirect ”comments.asp”
End If
End If%>

Som du säkert ser så har jag bantat ner formuläret till enbart den input som användaren skriver in captcha-koden på bilden. Du skapar alltså en bild (JPG förslagsvis) och ser till att skriva exakt samma teckenkombination i if-satsen i ASP-koden ovan. Om användaren/spamboten skriver in något annat än just den räätta kombinationen så skickas denne tillbaka till formulärsidan utan att något matas in i databasen.

Problem med betygsystem

Jag har kört fast i arbetet med att koda ett betygsystem till Favoritrecept.com. Det är ett simpelt script som bara adderar betygen 1-5 till en tabell, och för att få fram snittbetyget så ska den totala summan divideras med antalet betygsättningar. Problemet är bara att jag inte får inmatningen att funka på det aktuella recept-id man befinner sig på. Nu har jag suttit med skiten i tre nätter i rad och börjar bli uppgiven, speciellt eftersom jag misstänker att det är något simpelt misstag jag gjort.

Mer om referrer-scriptet

När jag skrivit klart förra inlägget kom jag på att jag redan har förbättrat det existerande referrer-scriptet en aning. Det handlar om funktionen som kollar upp om den aktuella hänvisande domänen ska blockeras eller matas in i databasen. Tidigare använde jag en lång och svåruppdaterad If-sats där adresserna lagrades direkt i koden. När jag bestämde mig för en ny lösning var denna If-sats redan 25 rader med fyra blockerade domäner per rad.

<%If url <> “www.google.se” AND url <> “www.google.com” AND url <> “www.google.dk” AND url <> “www.google.no” AND url <> “www.google.fi” Then%>

Nu har jag alltså förbättrat scriptet så att det söker igenom rader i en tabell och jämför med den aktuella hänvisningsdomänen för varje besök (som kommer via just en länk).

<%
Set Conn = Server.CreateObject(”ADODB.Connection”)
Conn.Open ”Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &Server.MapPath(”databasen\refererfilter_databas.mdb”)
Set RecSet = Server.CreateObject(”ADODB.RecordSet”)SQL = ”SELECT * FROM refererfilter WHERE url like ‘%”&url&”%'”
RecSet.Open SQL, Conn

If RecSet.EOF Then
‘Kod för inmatning
Else
End If
%>

Detta gör det mycket lättare att lägga till oönskade domäner/adresser i filtret, t.ex genom ett enkelt adminformulär. Jag kommer lägga upp hela det uppdaterade scriptet här på bloggen senare.