Skip to topic | Skip to bottom
Home

TechWeb11
TechWeb11.SpamProtocol13r1.6 - 12 Sep 2011 - 19:38 - FedericoBaroccitopic end

Start of topic | Skip to actions

SPAM Protocol

Specifiche di protocollo

Versione 1.3 , Settembre 2011

Questa versione: SpamProtocol13

Ultima versione: SpamProtocol13

Versione Precedente: SpamProtocol12

Autori: FabioVitali, AngeloDiIorio, SilvioPeroni, GioeleBarabucci

Abstract

Questo protocollo nasce all’interno del progetto SPAM del corso di Tecnologie Web 2011. L'obiettivo del progetto è la realizzazione di un sistema federato di microblog, noto appunto con il nome di SPAM("Social Production of Audiovisual Microblogs").

Il protocollo si compone in realtà di due protocolli diversi: PAM ("Protocol for Audiovisual Microblog") e UPIM ("Unified Protocol for Interoperable Microblogs").

L’architettura SPAM prevede infatti due componenti principali: client (per la creazione di post, visualizzazione, ricerca, etc.) e server (per il salvataggio dei documenti, propagazione dell'informazione, etc.). Ogni client comunica con il proprio server di riferimento tramite il protocollo PAM, mentre i server comunicano tra loro usando il protocollo UPIM.

Stato del documento

Questo documento è stato redatto da FabioVitali, AngeloDiIorio, SilvioPeroni e GioeleBarabucci. Deve essere utilizzato come materiale di riferimento per il progetto SPAM per garantire l’interoperabilità fra i gruppi. Questo documento è la versione 0.9.2 del protocollo ed è soggetto a modifiche da parte dei working group organizzati secondo le regole del W3C (http://www.w3.org/Consortium/Process/). I WG potranno emettere i documenti di riferimento aggiornati, numerati e versionati, che verranno usati per le specifiche di interoperabilità.

Introduzione

SPAM è un sistema federato di microblog. E' fondamentale quindi riconoscere in modo univoco le risorse indirizzabili nel sistema: utenti, server e post. Ad ogni server infatti sono associati più utenti, ognuno dei quali può scrivere più post.

In questo documento per evitare ambiguità si applicano le seguenti regole:

  • Ogni server è identificato da un identificatore univoco, chiamato "serverID" in questo documento.
  • Ogni utente è identificato da una coppia univoca "serverID/userID".
  • Ogni post è identificato da una tripla univoca "serverID/userID/postID".

I gruppi possono decidere anche una sintassi differente, purché sia garantita univocità all'interno della federazione.

Questo documento descrive le specifiche di entrambi i protocolli PAM e UPIM.

2. Protocollo PAM

PAM è un protocollo HTTP che regola la comunicazione tra client e server. Di seguito sono descritte tutte le possibili richieste previste. Le richieste sono progettate secondo l'architettura REST.

Per ogni richiesta è indicato:

  • il metodo HTTP
  • la struttura dell'URL, i parametri ed eventualmente gli esempi
  • il body della richiesta
  • l'header (e i codici HTTP) e il body della risposta.

Note generali:

  • Per poter eseguire azioni di modifica o inserimento di una risorsa sul server (e.g. punto 2.1, 2.2, 2.3) è necessario essere autenticati (vedasi paragrafo 1.)
  • Per inserire una risorsa (video/audio/immagine) è necessario utilizzare il seguente tag così formattato:
        <span resource="audio" src="link_audio" /> : per risorse audio
        <span resource="video" src="link_video" /> : per risorse video
        <span resource="image" src="link_immagine" /> : per risorse immagine
  • I termini del tesauro sono unici.

2.1 Meccanismi di Autenticazione

Tutte le operazioni descritte in questo documento prevedono autenticazione.

Per autenticarsi basta l'invio dell'username dal client al server, senza la necessità di alcuna password.

2.1.1 Login

Metodo: POST

URL: http://ltwxxxx.web.cs.unibo.it/login

Header:

Content-Type: application/x-www-form-urlencoded

Body:

username=username

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

vuoto

2.1.2 Logout

Metodo: POST

URL: http://ltwxxxx.web.cs.unibo.it/logout

Header:

Content-Type: application/x-www-form-urlencoded

Body:

vuoto

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

vuoto

L'utente che ha eseguito la richiesta non deve essere mai specificato nell'URL della richiesta ma usando i meccanismi appositi di HTTP.

Il server che creerà la sessione dovrà nominare il proprio cookie col seguente nome: ltwlogin

2.2 Invio nuovo post

L'invio di un nuovo post genera, sul server che riceve questa richiesta, un nuovo post il cui contenuto è passato nel corpo della richiesta.

Metodo: POST

URL: http://ltwxxxx.web.cs.unibo.it/post

Header:

Content-Type: application/x-www-form-urlencoded

Body:

article=
<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
</article>

Risposta

In caso di successo

Header:

HTTP/1.1 201 Created

Body:

vuoto

2.3 Respam post

Il respam di un nuovo post genera, sul server che riceve questa richiesta, un nuovo post il cui contenuto è dato dal post che si sta respammato.

Sarà il server in questo caso a recuperare l'articolo e salvarlo sul proprio server tramite i parametri passati del body. Vedasi UPIM.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/respam

Header:

Content-Type: application/x-www-form-urlencoded

Body:

serverID=<serverID>&userID=<userID>&postID=<postID>

Risposta

In caso di successo

Header:

HTTP/1.1 201 Created

Body:

vuoto

2.4 Rispondi al post

Rispondendo ad un post si genera, sul server che riceve questa richiesta, un nuovo post collegato a quello originale.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/replyto

Header:

Content-Type: application/x-www-form-urlencoded

Body:

serverID=<serverID>&
userID=<userID>&
postID=<postID>&
article=
<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
      <div rel="sioc:reply_of">
         <span resource="/tw10/gino/14" />
      </div>
</article>

Risposta

In caso di successo

Header:

HTTP/1.1 201 Created

Body:

vuoto

2.5 Ricerca post

È possibile effettuare delle ricerche sui post presenti all'interno della federazione. Queste ricerche possono essere di vario tipo:

  • i post di un autore
  • i post degli autore che si seguono
  • i post più recenti
  • i post che hanno a che fare con il post attualmente visualizzato
  • i post che hanno a che contengono una data stringa
  • i post i cui argomenti sono simili ad un dato argomento

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/search/<limit>/<type>/[<param>/]*

dove:

   * <limit>: all | 1 | 2 | ...
   * <type>: author | following | recent | related | fulltext | affinity

Esistono infatti sei chiavi di ricerca. I parametri variano a seconda della chiave usata, secondo il seguente schema:

author

http://ltwxxxx.web.cs.unibo.it/search/<limit>/author/<serverID>/<userID>

http://ltwxxxx.web.cs.unibo.it/search/10/author/tw18/pippo: restituiscimi i dieci più recenti post dell'utente "tw18/pippo".

following

http://ltwxxxx.web.cs.unibo.it/search/<limit>/following

http://ltwxxxx.web.cs.unibo.it/search/10/following : restituiscimi i dieci più recenti post degli utenti seguiti dall'utente che fa la richiesta (HTTP basic).

recent

http://ltwxxxx.web.cs.unibo.it/search/<limit>/recent/<term>

http://ltwxxxx.web.cs.unibo.it/search/10/recent/fc_roma: restituiscimi i dieci più recenti post che abbiano come argomento "fc_roma".

related

http://ltwxxxx.web.cs.unibo.it/search/<limit>/related/<term>

http://ltwxxxx.web.cs.unibo.it/search/10/related/fc_roma: restituiscimi i dieci post più correlati all'argomento "fc_roma" (ottenuti navigando e cercando nel tesauro).

fulltext

http://ltwxxxx.web.cs.unibo.it/search/<limit>/fulltext/<string>

http://ltwxxxx.web.cs.unibo.it/search/10/fulltext/ha%20fatto%20er%20cucchiaio: restituiscimi i dieci che contengono la stringa "ha fatto er cucchiaio" o parti di essa. Ogni server implementare politiche diverse, più o meno sofisticate, di ricerca full-text.

affinity

http://ltwxxxx.web.cs.unibo.it/search/<limit>/affinity/<serverID>/<userID>/<postID>

http://ltwxxxx.web.cs.unibo.it/search/10/affinity/tw18/pippo/12: restituiscimi i dieci post più affini al post "tw18/pippo/12".

Header/Body: vuoto.

Risposta

La risposta DEVE essere inviata utilizzando la seguente struttura XML:

<archive>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   .
   .
   .
</archive>

Spiegazione dei tag:

  • archive : elemento radice (root)
  • post : elemento contenente un articolo e alcune informazioni legate ad esso
  • content : header dell'articolo
  • affinity : valore di affinità dato all'articolo secondo la formula definita dalla sessione del 06/06/11
  • article : articolo vero e proprio

2.6 Richiesta post

È possibile recuperare il contenuto di un post a partire dal suo ID.

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/post/<serverID>/<userID>/<postID>

Header/Body: Body vuoto.

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
      <div rel="tweb:has_Group">
         <div typeof="tweb:like_Group">
            <span rel="tweb:has_member" resource="/tw12/pappo"></span>
            <span rel="tweb:has_member" resource="/tw12/peppo"></span>
            <span rel="tweb:has_member" resource="/tw12/puppo"></span>
         </div>
         <div typeof="tweb:dislike_Group">
            <span rel="tweb:has_member" resource ="/tw02/poppo"></span>
         </div>
      </div>
      <span property="tweb:countLike" content="1" />
      <span property="tweb:countDislike" content="5" />
      <div rel="tweb:like">
         <span resource="/tw15/pluto" />
      </div>
      <div rel="tweb:respamOf">
         <span resource="/tw10/tizio/10" />
      </div>
      <ul rel="sioc:has_reply">
         <li resource="/tw10/tizio/11" />
         <li resource="/tw09/caio/2" />
         <li resource="/tw01/semp/152" />
      </ul>
      <div rel="sioc:reply_of">
         <span resource="/tw10/gino/14" />
      </div>
</article>

Importante: obbligatorio specificare tramite RDFa le sequenti informazioni:

  • il valore di "like/dislike" dell'utente che ha fatto la richiesta.
  • il numero di "like" totali sul post
  • il numero di "dislike" totali sul post
  • se il post è un reply ad un altro post (<span rel="scioc:reply_of" resource="/tw34/pluto/76" />)
  • se il post è un respam ad un altro post (<span rel="tweb:respamOf" resource="/tw34/pluto/76" />)

2.7 Set "I like"

Tramite la richiesta setlike si imposta il grado di interesse dell'utente per un dato post.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/setlike

Header:

Content-Type: application/x-www-form-urlencoded

Body:

serverID=<serverID>&userID=<userID>&postID=<postID>&value=<value>

dove:

<value> : +1 (like)  |  -1 (dislike)

Risposta

Header:

HTTP/1.1 200 OK

Body:

vuoto

2.8 Richiesta lista server federati

Il client può richiedere al proprio server la lista dei server che si considerano all'interno della federazione, ossia quei server iscritti alla fiera. Il server dovrà tenere una copia di default (ossia la lista sopra citata) e una lista personalizzata per ogni utente.

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/servers

Header/Body: vuoto

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

Content-type: application/xml

<servers>
   <server serverID="tw2" serverURL="http://ltw0002.web.cs.unibo.it/" />
   <server serverID="tw3" serverURL="http://ltw0003.web.cs.unibo.it/" />
   <server serverID="tw4" serverURL="http://ltw0004.web.cs.unibo.it/" />
   <server serverID="tw11" serverURL="http://ltw0011.web.cs.unibo.it/" />
</servers>

2.9 Sovrascrittura lista server federati

Il client può fornire al proprio server la nuova lista dei server che si considerano all'interno della federazione.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/servers

Header:

Content-type: application/xml

Body:

servers=
<servers>
   <server serverID="tw2" serverURL="http://ltw0002.web.cs.unibo.it/" />
   <server serverID="tw3" serverURL="http://ltw0003.web.cs.unibo.it/" />
   <server serverID="tw4" serverURL="http://ltw0004.web.cs.unibo.it/" />
   <server serverID="tw11" serverURL="http://ltw0011.web.cs.unibo.it/" />
</servers>

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

vuoto

2.10 Set Follow su un utente

Il client può richiedere al server di considerare un certo utente come "seguito" e può anche decidere di non seguirlo più.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/setfollow

Header:

Content-Type: application/x-www-form-urlencoded

Body:

serverID=<serverID>&userID=<userID>&value=<value>

dove:

<value> : 0 (unfollow)  |  1 (follow)

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

vuoto

2.11 Richiesta lista utenti seguiti (followers)

Richiesta per recuperare la lista degli utenti che l'utente loggato sta seguendo. Il server, tramite la sessione, riconoscerà chi è l'utente che gli sta facendo la richiesta.

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/followers

Header/Body: vuoto

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

Content-type: application/xml

<followers>
  <follower id="tw11/pippo" />
  <follower id="tw11/paperino" />
  <follower id="tw10/pluto" />
  <follower id="tw09/topolino" />
</followers>

2.12 Aggiungi termine al tesauro esteso

È possibile aggiungere termini al tesauro condiviso, arrivando così al tesauro esteso. Per estendere il tesauro, il client fornisce al server il termine da usare come genitore e il nuovo termine foglia.

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/addterm

Header:

Content-Type: application/x-www-form-urlencoded

Body:

parentterm=<parentterm>&term=<term>

Esempi:

http://ltwxxxx.web.cs.unibo.it/addterm

parentterm=fc_roma
term=totti

http://ltwxxxx.web.cs.unibo.it/addterm

parentterm=totti&term=cucchiaio

Risposta

In caso di successo

Header:

HTTP/1.1 201 Created

Body:

vuoto

2.13 Restituisci il tesauro esteso

La risorsa thesaurus contiene il tesauro (sia condiviso che esteso) in formato SKOS, come descritto.

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/thesaurus

Header/Body: Body vuoto.

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

L'intero tesauro, nel formato SKOS descritto in sez. [XXX].

3. Protocollo UPIM

UPIM è un protocollo HTTP che regola la comunicazione tra server e server. Di seguito sono descritte tutte le possibili richieste UPIM. Alcune tra queste richieste sono sovrapposte con il protocollo PAM, poiché si occupano di propagare richieste dell'utente ai server che memorizzano altri post. Le richieste sono progettate secondo l'architettura REST.

Per ogni richiesta è indicato:

  • il metodo HTTP
  • la struttura dell'URL, i parametri ed eventualmente gli esempi
  • il body della richiesta
  • l'header (e i codici HTTP) e il body della risposta.

3.1 Ricerca post

È possibile effettuare delle ricerche sui post presenti all'interno della federazione. Queste ricerche possono essere di vario tipo:

  • i post di un autore
  • i post degli autore che si seguono
  • i post più recenti
  • i post che hanno a che fare con il post attualmente visualizzato
  • i post che hanno a che contengono una data stringa
  • i post i cui argomenti sono simili ad un dato argomento

Si impone che un singolo server non possa propagare

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/<type>/[<param>/]*

dove:

   * <limit>: all | 1 | 2 | ...
   * <type>: author | recent | related | fulltext | affinity

Esistono infatti sei chiavi di ricerca. I parametri variano a seconda della chiave usata, secondo il seguente schema:

author

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/author/<serverID>/<userID>

http://ltwxxxx.web.cs.unibo.it/searchserver/10/author/tw18/pippo: restituiscimi i dieci più recenti post dell'utente "tw18/pippo".

recent

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/recent/<term>

http://ltwxxxx.web.cs.unibo.it/searchserver/10/recent/fc_roma: restituiscimi i dieci più recenti post che abbiano come argomento "fc_roma".

related

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/related/<term>

http://ltwxxxx.web.cs.unibo.it/searchserver/10/related/fc_roma: restituiscimi i dieci post più correlati all'argomento "fc_roma" (ottenuti navigando e cercando nel tesauro).

fulltext

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/fulltext/<string>

http://ltwxxxx.web.cs.unibo.it/searchserver/10/fulltext/ha%20fatto%20er%20cucchiaio: restituiscimi i dieci che contengono la stringa "ha fatto er cucchiaio" o parti di essa. Ogni server implementare politiche diverse, più o meno sofisticate, di ricerca full-text.

affinity

http://ltwxxxx.web.cs.unibo.it/searchserver/<limit>/affinity/<serverID>/<userID>/<postID>/<k>/<j>

http://ltwxxxx.web.cs.unibo.it/searchserver/10/affinity/tw18/pippo/12/10/80: restituiscimi i dieci post più affini al post "tw18/pippo/12" usando come parametri k=1 e j=3

Header/Body: vuoto.

Risposta

La risposta DEVE essere inviata utilizzando la seguente struttura XML:

<archive>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   <post>
      <content>text/html; charset=UTF8</content>
      <affinity>5</affinity>
      <article>
         bla bla bla bla
      </article>
   </post>
   .
   .
   .
</archive>

Spiegazione dei tag:

  • archive : elemento radice (root)
  • post : elemento contenente un articolo e alcune informazioni legate ad esso
  • content : header dell'articolo
  • affinity : valore di affinità dato all'articolo secondo la formula definita nella riunione del 06/06/11
  • article : articolo vero e proprio

3.2 Richiesta di un post

È possibile recuperare il contenuto di un post a partire dal suo ID. La richiesta può essere effettuata solamente per un utente che risiede nel server indicato dall'url ltwxxxx.web.cs.unibo.it.

Metodo: GET

URL:

http://ltwxxxx.web.cs.unibo.it/postserver/<userID>/<postID>

Header/Body: Body vuoto.

Risposta

In caso di successo

Header:

HTTP/1.1 200 OK

Body:

<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
      <div rel="tweb:has_Group">
         <div typeof="tweb:like_Group">
            <span rel="tweb:has_member" resource="/tw12/pappo"></span>
            <span rel="tweb:has_member" resource="/tw12/peppo"></span>
            <span rel="tweb:has_member" resource="/tw12/puppo"></span>
         </div>
         <div typeof="tweb:dislike_Group">
            <span rel="tweb:has_member" resource ="/tw02/poppo"></span>
         </div>
      </div>
      <span property="tweb:countLike" content="1" />
      <span property="tweb:countDislike" content="5" />
      <div rel="tweb:like">
         <span resource="/tw15/pluto" />
      </div>
      <div rel="tweb:respamOf">
         <span resource="/tw10/tizio/10" />
      </div>
      <ul rel="sioc:has_reply">
         <li resource="/tw10/tizio/11" />
         <li resource="/tw09/caio/2" />
         <li resource="/tw01/semp/152" />
      </ul>
      <div rel="sioc:reply_of">
         <span resource="/tw10/gino/14" />
      </div>
</article>

Importante: obbligatorio specificare tramite RDFa le sequenti informazioni:

  • il valore di "like/dislike" dell'utente che ha fatto la richiesta.
  • il numero di "like" totali sul post
  • il numero di "dislike" totali sul post
  • la rimozione dei vari set-like o set-dislike forniti da tutti gli altri utenti, per ritornare al cliente solamente l'eventuale informazione di likeness del cliente richiedente, deve essere gestita dal server a cui questo fa riferimento.

3.3 Set "I Like"

Variazione del "Set Like". Necessario, infatti, aggiungere lo dell'utente che ha settato la preferenza. Ogni server può comunque scegliere le proprie policy di gestione delle preferenze (caching, limiti, etc.).

Metodo: POST

URL:

http://ltwxxxx.web.cs.unibo.it/propagatelike/
Dove nel body dovranno essere inserite le informazioni per fulluserID, value, e fullpostID

che, tenendo conto dei meccanismi di identificazione di server, utenti e post, si espande in:

http://ltwxxxx.web.cs.unibo.it/propagatelike/
Dove nel body dovranno essere inserite le informazioni per serverID1, userID1, value, serverID2, userID2, e postID2

Un esempio è mostrato in seguito:

serverID1=tw11&userID1=pippo&value=+1&serverID2=tw8&userID2=pluto&postID2=4

Risposta:

Body vuoto e codici HTTP appropriati.

3.4 Risposta al post

Il server notifica, al server su cui risiede il post originale, della creazione di un post di risposta. Il server che riceve la notifica aggiorna il post.

METODO: POST

URL:

http://lwtxxxx.cs.unibo.it/hasreply/
dove nel Body si avrà la struttura :
<serverID>=value&<userID>=value&.....

<serverID> = Id del server su cui risiede la risposta
<userID> = Id dell'user che ha generato la risposta
<postID> = Id del post di Risposta
<userID2Up> = Id dell'user che ha generato il post da aggiornare
<postID2Up> = Id del post da aggiornare

Il server arricchisce il post con:

<span rel="sioc:has_reply" resource="/serverID/userID/postID" />

Risponde:

In caso di successo:

HEADER:

HTTP/1.1 200 OK

4. Gestione degli errori

Nel caso in cui una richiesta generi un errore, il server DEVE rispondere utilizzando gli appropriati codici HTTP 4xx e 5xx. I client DEVONO gestire ogni codice d'errore in maniera appropriata.

Client e server DEVONO gestire almeno questi errori (con relativi codici HTTP):

401 Forbidden
non è possibile accedere alla risorsa perché non si ha l'autorizzazione per farlo
404 Not available
risorsa non disponibile
405 Method not allowed
il servizio è stato chiamato con un metodo HTTP non previsto (ad esempio GET piuttosto che POST).
406 Not acceptable
non è possibile erogare il servizio perché i vincoli della richiesta non sono soddisfacibili.
500 Internal server error
c'è stato un problema interno al servizio durante l'elaborazione dalla richiesta.
501 Not implemented
il servizio richiesto non è fornito.

In aggiunta ai codici d'errore HTTP, il contenuto fornito dal server deve fornire più indicazioni possibili sull'errore generato e fornire suggerimenti su come risolverlo. I servizi sono liberi di usare qualsiasi tipo di dato per il contenuto restituito, tenendo comunque in considerazione la richiesta originaria del client (fornite nell'header Accept o in altro modo).

5. Tesauro

La tassonomia condivisa da usare è descritta dalla seguente lista annidata, dove gli annidamenti definiscono relazioni via via sempre più circoscritte e precise:

  • sport
    • calcio
      • portiere
      • difensore
      • centrocampista
      • attaccante
    • pallavolo
      • schiacciatore
      • palleggiatore
      • allenatore
      • arbitro
    • nuoto
      • stile_libero
      • farfalla
      • delfino
      • dorso
    • tennis
      • racchetta
      • pallina
      • terra_battuta
      • cemento
      • erba
      • sintetico
  • musica
    • genere
      • rock
      • jazz
      • classica
      • pop
    • strumenti
      • chitarra
      • tastiera
      • piano
      • batteria
      • sassofono
      • tromba
      • sintetizzatore
    • media
      • cd
      • mp3
      • vinile
      • wav
      • streaming
  • letteratura
    • genere
      • fantascienza
      • fantasy
      • storia
      • epistolare
      • filosofia
    • ruolo
      • autore
      • editore
      • lettore
      • distributore
    • tipologia
      • romanzo
      • racconto
      • poesia
      • collana

La tassonomia condivisa, così come le estese, deve essere implementata in SKOS nella linearizzazione XML per RDF, di cui qui forniamo una prima implementazione, non ancora da considerarsi definitiva.

Per quanto riguarda il Tesauro, indicherà il termine del tesauro condiviso come accedibile dall'URI con pathening iniziale http://vitali.web.cs.unibo.it/thesaurus/..., mentre si indicherà con http://ltwxxxx.web.cs.unibo.it/thesaurus/... quello del tesauro esteso. Nota: con xxxx si indica il numero del gruppo di cui abbiamo il tesauro. Inoltre, per calcolare la formula sull'affinità, si fa riferimento al file caricato nel resoconto della riunione del 06/06/11

6. RDFa

Ogni post creato, anche a seguito di una risposta ad un altro post o a un retweet, deve arrivare al server opportunamente arricchito, sia di costrutti HTML sia di definizioni semantiche, espresse via RDFa. Ad esempio, si consideri il seguente post (come viene scritto da un utente utilizzando il client):

Testo di un post contenente #hashtag, altri hashtag che si riferiscono a
concetti del tesauro condiviso (ad esempio #portiere) o del tesauro esteso (ad
esempio #roma) e altro html sparso (ad esempio, http://www.example.com)

Questo testo viene (automaticamente o semi-automaticamente) arricchito con opportuni elementi HTML:

<article>
   Testo di un post contenente #hashtag, altri hashtag che si riferiscono a
   concetti del tesauro condiviso (ad esempio #portiere) o del tesauro esteso
   (ad esempio #roma) e altro html sparso (ad esempio, 
   <a href="http://www.example.com">http://www.example.com</a>)
</article>

Oltre a ciò, è necessario indicare, in qualche modo, le altre informazioni relative al post, ad esempio che i tag liberi ("hashtag" nell'esempio) e i termini del tesauro usati ("/sport/calcio/portiere" dal tesauro controllato e "/sport/calcio/portiere/roma" dal tesauro esteso) siano resi esplicitamente argomenti di questo post. Questo deve essere fatto usando RDFa:

<article>
   Testo di un post contenente
   <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
   altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
   <span rel="sioc:topic">#
      <span typeof="skos:Concept" 
         about="/sport/calcio/portiere" 
         rel="skos:inScheme"
         resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">
         portiere</span>
   </span>)
   o del tesauro esteso (ad esempio
   <span rel="sioc:topic">#
   <span typeof="skos:Concept" 
      about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme"
      resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
   e altro html sparso (ad esempio, <a href="http://www.example.com">http://www.example.com</a>)
</article>

Inoltre, una volta arrivato al server, vengono aggiunte ulteriori asserzioni RDFa (riguardanti l'autore, l'uri della risorsa che identifica il post, ecc.) in modo da meglio descrivere il post stesso, es:

<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
      <div rel="tweb:has_Group">
         <div typeof="tweb:like_Group">
            <span rel="tweb:has_member" resource="/tw12/pappo"></span>
            <span rel="tweb:has_member" resource="/tw12/peppo"></span>
            <span rel="tweb:has_member" resource="/tw12/puppo"></span>
         </div>
         <div typeof="tweb:dislike_Group">
            <span rel="tweb:has_member" resource ="/tw02/poppo"></span>
         </div>
      </div>
      <span property="tweb:countLike" content="1" />
      <span property="tweb:countDislike" content="5" />
      <div rel="tweb:like">
         <span resource="/tw15/pluto" />
      </div>
      <div rel="tweb:respamOf">
         <span resource="/tw10/tizio/10" />
      </div>
      <ul rel="sioc:has_reply">
         <li resource="/tw10/tizio/11" />
         <li resource="/tw09/caio/2" />
         <li resource="/tw01/semp/152" />
      </ul>
      <div rel="sioc:reply_of">
         <span resource="/tw10/gino/14" />
      </div>
</article>

Gli oggetti e le relazioni, minimi ed obbligatori, da usare per le varie descrizioni di un post sono i seguenti:

  • sioc:Post – identifica un post pubblicato da un certo utente
  • dcterms:created – descrive la data di creazione di un post
  • sioc:has_creator – collega un post al suo autore
  • sioc:topic – collega un post con gli argomenti (tag o termini del tesauro) a cui fa riferimento
  • sioc:reply_of – identifica un post come risposta di un altro post
  • tweb:respamOf – identifica un post come respam di un altro post
  • tweb:countLike – descrive a quanti utenti è piaciuto un post
  • tweb:countDislike – descrive a quanti utenti non è piaciuto un post
  • skos:Concept – identifica un termine del tesauro
  • skos:inScheme – collega un termine con il tesauro che lo definisce
  • ctag:Tag – identifica un termine libero non legato al tesauro
  • ctag:label – descrive l'etichetta di un tag
  • tweb:like – collega un utente ad un post che gli è piaciuto
  • tweb:dislike – collega un utente ad un post che non gli è piaciuto

Fare riferimento ai vocabolari SIOC, Common Tag e SKOS per maggiori dettagli. Il prefisso tweb si riferisce a http://vitali.web.cs.unibo.it/vocabulary/.

7. Registrazione dei server SPAM

Ogni server deve registrarsi alla federazione SPAM, per potere rendere disponibili i propri contenuti e servizi.

La registrazione non avviene in maniera automatica ma modificando manualmente un file XML condiviso da tutti i gruppi. E' compito del working group decidere l'URL del registro SPAM.

Alla fine di ogni fiera, i gruppi sono tenuti a redarre il file XML condiviso. I gruppi dovranno inoltre consegnare una copia del file al docente o pubblicarlo sul wiki. Questa versione NON DEVE essere ulteriormente modificata.

Ogni server dovrà richiedere questo file (tramite un GET HTTP) e usarlo per riconoscere i file della federazione.

Il registro XML è stato caricato in questo file.

8. TRAM: Testing Reliability of Audiovisual Microblogs

TRAM è la test suite di SPAM. Il suo scopo è accertarsi che le implementazioni di SPAM siano conformi alle richieste del protocollo.

<test-suite>

La test suite è composta da una serie di test.

<!ELEMENT test-suite (test)*>

<test>

Ognuno di questi test ha:

  • un nome che identifica cosa si sta testando;
  • una o più azioni da compiere per valutare il test;
  • una descrizione di cosa ci si aspetta.

<!ELEMENT test (name, action+, expect)>

<name>

Nome di che cosa si sta testando.

<!ELEMENT name (#PCDATA)>

<action>

L'azione da compiere e` descritta da:

  • il metodo da usare;
  • un frammento URI da usare per comporre l'URI verso quale fare la richiesta di test;
  • una serie di coppie chiave-valore da usare come header della richiesta di test;
  • una serie di byte da usare come corpo della richiesta di test;

<!ELEMENT action (method, uri, headers, body?)>

<!ELEMENT method (#PCDATA)>
<!ELEMENT uri (#PCDATA)>
<!ELEMENT headers (header)>
<!ELEMENT header EMPTY>
<!ATTLIST header
   name CDATA #REQUIRED
   value CDATA #REQUIRED
>
<!ELEMENT body (#PCDATA)>

<expect>

La descrizione di ciò che ci si aspetta in risposta è composta da:

  • un codice HTTP;
  • una serie di byte che dovrebbero essere restituiti come corpo della richiesta fatta.

<!ELEMENT expect (status, body?)>

<!ELEMENT status (#PCDATA)>
<!ELEMENT body (#PCDATA)>

Variabili

All'interno di ogni test posso comparire variabili che, al momento del lancio dei test, saranno sostituite con valori appropriati.

Le variabili possibili sono:

  • ${serverID-ok}
  • identificativo di un server che si sa esistente e funzionante;
  • ${userID-ok}
  • identificativo di un utente che si sa esistente su ${serverID-ok};
  • ${postID-ok}
  • identificativo di un post che si sa esistente su ${serverID-ok} e generato da ${userID-ok};

  • ${serverID-err}
  • identificativo di un server che si sa NON esistente o NON funzionante;
  • ${userID-err}
  • identificativo di un utente che si sa NON esistente su ${serverID-ok};
  • ${postID-err}
  • identificativo di un post che si sa NON esistente su ${serverID-ok} o NON generato da ${userID-ok};

Si e' deciso al fine di semplificare il processo di testing di usare un valore di default riconosciuto come errato, e che quindi non potrà mai essere considerato come cme userID, postID o come serverID valido.

  • ${serverID-err}: ltw0000
  • ${userID-err}: user0
  • ${postID-err}: 0000

Esempi di test

Retweet di un post non esistente ad un server esistente deve restituire un errore.

<test>
   <name>Retweet di un post non esistente ad un server esistente deve restituire un errore</name>
   <action>
      <method>put</method>
      <uri>/retweet/lw18/admin/${postID-err}</uri>
      <headers/>
   </action>
   <expect>
      <status>404</status>
   </expect>
</test>

8.1 TRAM-PAM

TRAM-PAM testa il protocollo client/server PAM.

File XML dei test PAM

8.2 TRAM-UPIM

TRAM-UPIM testa il protocollo server/server UPIM. Include tutti i test di TRAM-PAM piu` altri specifici del protocollo UPIM.

File XML dei test UPIM

9. Esempio di percorso di un post

9.1 Articolo iniziale

Testo semplice inserito dall'utente.

Testo di un post contenente #hashtag, altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio
#portiere) o del tesauro esteso (ad esempio #roma) o link sparsi (ad esempio, http://www.example.com),
e perché no un po' di audio (ad esempio, http://www.example.com/song.mp3),
o un po' di video (ad esempio, http://www.example.com/video.ogv),
e immagini (ad esempio, http://www.example.com/pic.png).

9.2 Articolo arricchito lato client

Il testo semplice sopra inserito viene letto e arricchito di nuovi tag HTML e XML: il risultato verrà poi inviato al server.

<article>
   Testo di un post contenente 
   <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
   altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
   <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
   rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
   o del tesauro esteso (ad esempio 
   <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
   rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
   o link sparsi (ad esempio, http://www.example.com),
   e perché no un po' di audio (ad esempio, 
   <span resource="audio" src="http://www.example.com/song.mp3" />),
   o un po' di video (ad esempio, 
   <span resource="video" src="http://www.example.com/video.ogv" />),
   e immagini (ad esempio, 
   <span resource="image" src="http://www.example.com/pic.png" />).
</article>

9.3 Articolo finito

L'articolo soprastante arriva al server e questo lo arricchisce di ulteriori informazioni. Ora l'articolo è pronto per essere salvato.

<article prefix="
   sioc: http://rdfs.org/sioc/ns#
   ctag: http://commontag.org/ns#
   skos: http://www.w3.org/2004/02/skos/core#
   dcterms: http://purl.org/dc/terms/
   tweb: http://vitali.web.cs.unibo.it/vocabulary/"
   about="/tw12/pippo/11" typeof="sioc:Post" rel="sioc:has_creator" resource="/tw12/pippo"
   property="dcterms:created" content="2006-09-07T09:33:30Z">
      Testo di un post contenente 
      <span rel="sioc:topic">#<span typeof="ctag:Tag" property="ctag:label">hashtag</span></span>,
      altri hashtag che si riferiscono a concetti del tesauro condiviso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere" 
      rel="skos:inScheme" resource="http://vitali.web.cs.unibo.it/TechWeb11/thesaurus">portiere</span> </span>)
      o del tesauro esteso (ad esempio 
      <span rel="sioc:topic">#<span typeof="skos:Concept" about="/sport/calcio/portiere/roma" 
      rel="skos:inScheme" resource="http://ltw11.web.cs.unibo.it/thesaurus">roma</span></span>)
      o link sparsi (ad esempio, http://www.example.com),
      e perché no un po' di audio (ad esempio, 
      <span resource="audio" src="http://www.example.com/song.mp3" />),
      o un po' di video (ad esempio, 
      <span resource="video" src="http://www.example.com/video.ogv" />),
      e immagini (ad esempio, 
      <span resource="image" src="http://www.example.com/pic.png" />).
      <div rel="tweb:has_Group">
         <div typeof="tweb:like_Group">
            <span rel="tweb:has_member" resource="/tw12/pappo"></span>
            <span rel="tweb:has_member" resource="/tw12/peppo"></span>
            <span rel="tweb:has_member" resource="/tw12/puppo"></span>
         </div>
         <div typeof="tweb:dislike_Group">
            <span rel="tweb:has_member" resource ="/tw02/poppo"></span>
         </div>
      </div>
      <span property="tweb:countLike" content="1" />
      <span property="tweb:countDislike" content="5" />
      <div rel="tweb:like">
         <span resource="/tw15/pluto" />
      </div>
      <div rel="tweb:respamOf">
         <span resource="/tw10/tizio/10" />
      </div>
      <ul rel="sioc:has_reply">
         <li resource="/tw10/tizio/11" />
         <li resource="/tw09/caio/2" />
         <li resource="/tw01/semp/152" />
      </ul>
      <div rel="sioc:reply_of">
         <span resource="/tw10/gino/14" />
      </div>
</article>

10. Linee Guida

Di seguito le linee guida per implementare il progetto.

10.1 RDF Injection

Ogni server dovrà inserire l'apposito codice RDF all'interno di ogni articolo appena creato: in particolare dovrà gestire i Reply e i Respam.

Quando un articolo è considerato un reply di un altro, è necessario inserire alla fine di esso (ovviamente a lato server) il seguente tag span:

<span rel="sioc:reply_of" resource="/tw34/pluto/76" />

Invece quando un articolo è considerato un respam di un altro, è necessario inserire il seguente tag span:

<span rel="tweb:respamOf" resource="/tw34/pluto/76" />

Dove resource sta per l'articolo replyato o respammato.

Per quanto riguarda l'inserimento degli altri codici RDF, si consiglia la lettura dell'apposito paragrafo.

10.2 File di Progetto

I file ufficiali che dovranno essere utilizzati nel progetto sono indicati nella seguente pagina: X-FILES

10.3 12CFU

Di seguito le linee guida per i progetti del vecchio ordinamento (12CFU).

10.3.1 Linked Data

Per differenziare i server e i client da 6 CFU con quelli da 12, tutti gli header delle richieste sono da fare nel seguente modo:

Content-type: text/html, application/xml, application/rdf-xml, text/html+xml, ...; charset=UTF-8

al posto di:

Content-type: text/html; charset=UTF-8

Questo perché i gruppi da 12CFU devono poter soddisfare richieste di vario tipo, oltre al semplice text/html.

10.3.2 Geo Location

Ogni articolo deve contenere una geolocazione, ossia un tag <span> particolare formato da un identificativo (geolocationspan) e dalle coordinate geografiche. Di seguito un esempio:

<span id="geolocationspan" long="0000.0000" lat="0000.0000" />

I progetti da 6CFU dovranno ignorare questi particolari hashtag.

11. Modifiche rispetto alle versioni precedenti

  • Eliminazione del valore 0 in "value" del punto 2.7 Set "I like"
  • Modifica della struttura del file XML dei server (aggiunto serverURL)
  • Modifica della struttura XML di * "article" *

-- FedericoBarocci - 12 Sep 2011

  • Set ALLOWTOPICVIEW =
  • Set ALLOWTOPICCHANGE =

to top

You are here: TechWeb11 > SpamProtocol13

to top

Copyright © Fabio Vitali 2014 Last update of SpamProtocol13 on 12 Sep 2011 - 19:38 by FedericoBarocci