Jump to content
magician

Desafio de Programação

Gostariam de mais desafios deste género?  

36 members have voted

  1. 1. Gostariam de mais desafios deste género?

    • Sim
      33
    • Não
      2


Recommended Posts

magician

Ora bem tenho aqui um pequeno desafio para quem quiser, quem quizer resolver está convidado a fazê-lo podem usar qualquer linguagem de programação basta apenas respeitar a restrições impostas no desafio :(

Tarefas :

    - Aceder à pagina http://feeds.feedburner.com/revistaprogramar_pdfs?format=xml usando apenas sockets e implementando o protocolo necessário.

    - Fazer a leitura do ficheiro e retirar os seguintes dados

        -> title

        -> link

        -> enclosure

    - A os dados devem ser apresentados pela consola com o seguinte formato :

        Titulo : X Edição - XXXX de 200X

        Link : http://www.portugal-a-programar.org/revista-programar/edicoes/....pdf

        URL : http://www.portugal-a-programar.org/revista-programar/edicoes/....pdf

        Tamanho : 2717712 bytes

        Tipo : application/pdf

Restrições :

    Não devem ser utilizadas bibliotecas de conexão HTTP, a ligação deve ser feita pelo método GET aplicado a sockets.

    No caso de linguagens WEB não devem ser usadas libs como CURL e afins.

Todas as linguagens que suportem Sockets por ser usadas.

Libs para leitura de XML como DOM ou SAX podem ser usadas mesmo sendo externas ao core da linguagem.

As resoluções devem ser postadas aqui e apresentadas com a ajuda do GeSHi.

Qualquer questão é só postar aqui ou mandar uma PM :)

Já agora aproveitem e votem na pool :)


I haven’t lost my mind; it’s backed up on DVD somewhere!

Share this post


Link to post
Share on other sites
magician

Vais ter que o mostrar LOL

Eu já fiz o desafio em Java mas quero ver como se safam :(


I haven’t lost my mind; it’s backed up on DVD somewhere!

Share this post


Link to post
Share on other sites
djthyrax

Vais ter que o mostrar LOL

Eu já fiz o desafio em Java mas quero ver como se safam :)

Pois vou, mas não vai ser ainda eheh. :(

Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
Betovsky

hehe porreiro. Até era menino para tentar fazer isto em Haskell. Tenho que ver que bibliotecas existem disponiveis para fazer a ligação.


"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Share this post


Link to post
Share on other sites
djthyrax

Tenho que ver que bibliotecas existem disponiveis para fazer a ligação.

Só podes usar sockets.

Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
Betovsky

Tenho que ver que bibliotecas existem disponiveis para fazer a ligação.

Só podes usar sockets.

Claro, claro. Mas é a primeira vez que estou a usar ligações externas em Haskell, tive que andar haver como é que era, ler documentação praticamente inexistente, etc. E ao fim de um par de horas já pus a ir buscar o xml. Hurray  :wallbash:

Bem agora vou dormir que já se faz tarde e amanhã vai ser um dia penoso /me olha para as horas.

Fica uma pergunta, qual é a diferença entre link e url a ser mostrado pela aplicação?


"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Share this post


Link to post
Share on other sites
MX+

Está feito. A minha pergunta é se publico já o código ou espero que haja mais participações?

PS: O encoding de cedilhas e acentos no MSDos está fora do meu controlo, posso adaptar e converter caracteres acentuados, mas de qualquer forma fica já aqui o trabalho feito.

euzzlyygld.PNG

mk0des0hao.PNG

Share this post


Link to post
Share on other sites
djthyrax

Uma coisa magician, queres o output:

1º edicção

2º edição

3º edicaçõ

...

ou pode ser:

...

3º edicaçõ

2º edicção

1º edição

?


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
TheDark

Também acabei o meu. Em C++. Sem bibliotecas externas, e com sockets do Linux.

progrevistayj1.png


Desaparecido.

Share this post


Link to post
Share on other sites
djthyrax

526080it_works.png

Custou mas foi (e está tãaaaaaaaaaaaaaaaaaaaaaaaaaaaao dirty este código :x). :(


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
magician

Ainda bem que gostarem do desafio :( quando poder posto a minha solução em Java, já vi que temos soluções em C++, Python e até PHP :)

Se quiserem podem postar o código usem o GeSHi :)


I haven’t lost my mind; it’s backed up on DVD somewhere!

Share this post


Link to post
Share on other sites
djthyrax
#!/usr/bin/python
# -*- coding: utf-8 -*-
##########################################
# XML Sockets Programar                  #
# by djthyrax                            #
#                                        #
#   blame all the dirty code in magician #
##########################################
# http://portugal-a-programar.org        #
# (O Triton é uma bicha)                 #
##########################################

import socket, sys
from xml.dom import minidom

class UrlParser: ## URL Parser
def __init__(self, parent, url):
	self.url = url
	self.parent = parent

def parse(self):
	try:
		protocol, resto = self.url.split("//", 1)

		if not protocol in self.parent.protocols:
			raise TypeError # Foi a primeira exception que me veio à cabeça...

		stuff = resto.split("/", 1)
		self.host = stuff[0]
		self.uri = "/"+stuff[1] # O URI começa sempre com /

		if not self.host:
			raise TypeError

		try: # encontrar fragmentos
			self.uri, self.fragment = self.uri.split("#", 1)
		except:
			pass
		return True
	except:
		return False

class Connection: ## Ligação
def __init__(self, host, port, connect, part):
	self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	self.host = host
	self.port = port
	self.part = part
	if connect:
		self.connect()

def connect(self):
	try:
		self.socket.connect((self.host, self.port)) # Connect it bitch!
		return True
	except:
		return False

def communicate(self, content):
	self.socket.send(content)
	self.buffer = []
	while True:
		tmp = self.socket.recv(4096)
		if self.part: # Dirty Hack para ter só os 2 headers que preciso :F
			if 'Content-Type' in ''.join(self.buffer) and 'Content-Length' in ''.join(self.buffer):
				break
		if not tmp:
			break
		self.buffer.append(tmp)
	self.socket.close()
	self.reply = ''.join(self.buffer)
	return self.reply


class HttpHeader: # Yay for classes!
def __init__(self, name, value):
	self.name = name
	self.value = value
	self.representation = "%s: %s" % (self.name, self.value) # É tão giro poupar no código ^_^

class HttpRequest: # Request
def __init__(self, parent, method, uri, part):
	self.headers = []
	self.method = method
	self.uri = uri
	self.conn = Connection(parent.url.host, 80, True, part) # abrir uma ligação

def setHeader(self, name, value):
	self.headers.append(HttpHeader(name, value))

def setHeaders(self, headers): # Yay for shortcuts 
	for name in headers:
		value = headers[name]
		self.setHeader(name, value)

def getHeaders(self):
	returns = ''
	for header in self.headers:
		returns += "%s\r\n" % (header.representation)
	return returns

def communicate(self):
	self.textToSend = ''
	self.textToSend += "%s %s HTTP/1.0\r\n" % (self.method, self.uri)
	self.textToSend += self.getHeaders()
	self.textToSend += "\r\n"
	self.reply = self.conn.communicate(self.textToSend) # Ouve-me cabra! 
	return self.reply


class Program:
def __init__(self, url, part):
	self.protocols = ["http:"] # É sempre bom prepararmo-nos para o futuro
	self.url = url
	self.part = part

def start(self):
	self.url = UrlParser(self, self.url) # Parsa o raio do URL
	if not self.url.parse(): # Something happen
		print "Ups. Aconteceu um erro."
		sys.exit(0)
	# Bora lá!
	self.request = HttpRequest(self, 'GET', self.url.uri, self.part) # Ligar
	self.request.setHeader('Host', self.url.host) # Passar pelos vHosts
	self.reply = self.request.communicate() # Comunicar
	if '\r\nLocation: ' in self.reply.split("\r\n\r\n")[0]: # Raios parta os redireccionamentos, só me fazem sujar o código...
		self.reply = self.reply.split("\r\n\r\n")[0]
		for header in self.reply.split("\r\n"):
			header = header.split(": ", 1)
			if header[0] == 'Location':
				if not "http:" in header[1]:
					self.reply = Program('/'.join(self.url.url.split("/")[0:-1])+'/'+header[1], True) # eheh.
					self.reply.start()
					self.reply = self.reply.reply

def parseXml(self):
	self.xml = self.reply.split("\r\n\r\n", 1)[1] # Nós queremos o body da resposta, os headers não interessam
	self.xml = minidom.parseString(self.xml) # Yay for DOM!
	self.edicoes = self.xml.getElementsByTagName("item")

def parseHeaders(self):
	self.headers = self.reply.split("\r\n\r\n", 1)[0] # Not body, headers. 
	self.headers = self.headers.split("\r\n") # Dividir os headers
	returns = { }
	for header in self.headers:
		header = header.split(": ", 1)
		if header[0] == 'Content-Type':
			returns['type'] = header[1]
		elif header[0] == 'Content-Length':
			returns['length'] = header[1]
	return returns

def showEdicoes(self):
	for edicao in self.edicoes:
		print u"Título: %s" % (edicao.childNodes[1].childNodes[0].data) # Nem imaginam as voltas que eu dei à pala do childNodes[0]...
		print "Link: %s" % (edicao.childNodes[5].childNodes[0].data)
		print "URL: %s" % (edicao.childNodes[5].childNodes[0].data)
		self.edicao = Program(edicao.childNodes[5].childNodes[0].data, True)
		self.edicao.start()
		details = self.edicao.parseHeaders()
		print "Tamanho: %s bytes" % (details["length"])
		print "Tipo: %s" % (details["type"])
		print


root = Program("http://feeds.feedburner.com/revistaprogramar_pdfs?format=xml", False) # woot. chain reactiong start. piriripum. *robot sound*
root.start()
root.parseXml()
root.showEdicoes()

# IT WORKS, GIVE ME COOKIES!

Sim, eu sei que está dirty. Mas como diz o rolando2424, "foi feito assim à pressa". :)


Não peças ajuda por PM! A tua dúvida vai ter menos atenção do que se for postada na secção correcta do fórum!

Share this post


Link to post
Share on other sites
TheDark

Após alteração de algumas coisitas, nomeadamente a criação da classe Enclosure e das funções auxiliares, aqui fica um código igualmente a dar para o feio:

#include <cstdio>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <string>

const unsigned int BUFFSIZE = 1024;

class TDsocket {
int socketDescriptor;
struct sockaddr_in serverAddress;
struct hostent *hostInfo;

public:

void open(char *hostname, unsigned short int port) {

	hostInfo = gethostbyname(hostname);
	if (hostInfo == NULL) {
		printf("Problema ao obter host: %s\n", hostname);
		return;
	}

	socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
	if (socketDescriptor < 0) {
		printf("Impossível criar socket\n");
		return;
	}

	serverAddress.sin_family = hostInfo->h_addrtype;

	memcpy((char *) &serverAddress.sin_addr.s_addr,
			   hostInfo->h_addr_list[0], hostInfo->h_length);

	serverAddress.sin_port = htons(port);
	if (connect(socketDescriptor, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
		printf("Impossível ligar\n");

}

void get(char *req, std::string *xb) {

	if (::send(socketDescriptor, req, strlen(req)+1, 0) < 0) {
		printf("Erro ao enviar pedido GET\n");
		close(socketDescriptor);
		return;
	}

	char buff[bUFFSIZE];

	int r=0;

	sleep(2);
	do{
		memset(buff, 0x0, BUFFSIZE);
		r=recv(socketDescriptor, buff, BUFFSIZE-1, 0);
		xb->append(buff);
	} while (r == BUFFSIZE-1);

	close(socketDescriptor);
}
};

class Enclosure {
const std::string *orig;

void encFill(std::string::size_type &s2 /*start*/) {

	std::string::size_type
		s1 = orig->find("url=\"", s2),
		sz = 5;

	s2 = orig->find('"', s1+sz);

	if (s1 != std::string::npos && s2 != std::string::npos)
		url=orig->substr(s1+sz, s2-(s1+sz));

	s1 = orig->find("length=\"", s2),
	sz = 8;

	s2 = orig->find('"', s1+sz);

	if (s1 != std::string::npos && s2 != std::string::npos)
		length=orig->substr(s1+sz, s2-(s1+sz));

		s1 = orig->find("type=\"", s2),
		sz = 6;

	s2 = orig->find('"', s1+sz);

	if (s1 != std::string::npos && s2 != std::string::npos)
		type=orig->substr(s1+sz, s2-(s1+sz));
}

public:
std::string url, length, type;

Enclosure(std::string *_orig, std::string::size_type _pos): orig(_orig) {
	encFill(_pos);
}
};

bool getTagContent(const std::string &fullstring, const std::string &tag, std::string::size_type &start, std::string &content) {

std::string fulltag("<"), fullendtag("</");
fulltag.append(tag + ">");
fullendtag.append(tag + ">");

content.clear();

std::string::size_type
	s1 = fullstring.find(fulltag, start),
	sz = fulltag.length();

start = fullstring.find(fullendtag, s1);

if (s1 == std::string::npos || start == std::string::npos)
	return false;

content=fullstring.substr(s1+sz, start-(s1+sz));

return true;
}

int main(int argc, char **argv) {

std::string xmlbuffer;
xmlbuffer.clear();

TDsocket tds;
tds.open("feeds.feedburner.com", 80);
char *req = "GET /revistaprogramar_pdfs?format=xml HTTP/1.1\n"
			"Host: feeds.feedburner.com\n\n";

tds.get(req, &xmlbuffer);

std::string::size_type s2=0;

printf("----------------------------------\n");

s2 = xmlbuffer.find("<item>", 0);
std::string tagct;
tagct.clear();

while (true) {

	if (getTagContent(xmlbuffer, "title", s2, tagct) == false)
		break;
	printf("Titulo : %s\n", tagct.c_str());

	if (getTagContent(xmlbuffer, "link", s2, tagct) == false)
		break;
	printf("Link : %s\n", tagct.c_str());

	s2 = xmlbuffer.find("<enclosure ", s2);

	Enclosure enclosure(&xmlbuffer, s2);

	printf("URL : %s\nTamanho : %s\nTipo : %s\n",
		enclosure.url.c_str(), enclosure.length.c_str(), enclosure.type.c_str());

	printf("----------------------------------\n");

}

return 0;
}


Desaparecido.

Share this post


Link to post
Share on other sites
kingless

Não acabei o script como queria porque tenho alguns trabalhos mais importantes a fazer por isso fica aqui o que fiz...

capturaecra1ng4.th.png

<?php

$feed = new FeedGet();
$feed->display();

class FeedGet {

var $feedurl = 'http://feeds.feedburner.com/revistaprogramar_pdfs?format=xml';
var $parsedXML = null;

function FeedGet( $feedurl = null, $show = array( 'link', 'size', 'title', 'type' ) ) {

	if(!empty( $feedurl )) {
		$this->feedurl = $feedurl;
	}

	$data = $this->getData();

	$this->parseXML( $data, $show );
}

function getData() {

	$data = file_get_contents( $this->feedurl );

	return $data;
}

function parseXML( $data, $show ) {

	$exp1 = explode( '<item>', $data );
	$parsed = array();
	$x = 0;

	foreach( $exp1 as $items ) {
		$exp = explode( '</item>', $items );

		$item = $exp[0];

		foreach( $show as $value ) {

			if($value == 'link' || $value == 'url' || $link = 'title' ) {

				if(preg_match( '/<('. $value .')>(.*)<\/'. $value .'>/i', $item, $match )) {

					$parsed[$x][$match[1]] = $match[2];
				}
			}

			if(preg_match( '/<enclosure(.*)length="(.*)"\s+type="(.*)"\s*\/>/i', $item, $match )) {

				if($value == 'type' && !empty( $match[3] )) {
					$parsed[$x][$value] = $match[3];
				}

				if($value == 'size' && !empty( $match[2] )) {
					$parsed[$x][$value] = $match[2];
				}
			}
		}
		$x++;
	}

	$this->parsedXML = $parsed;
}

function display() {

	if(is_null( $this->parsedXML )) {
		return false;
	}

	foreach( $this->parsedXML as $xml ) {
		$display[] = 'Titulo: '. $xml['title'] ."\r\nLink: ". $xml['link'] ."\r\nSize: ". $xml['size'] ."\r\nType: ". $xml['type']."\r\n";
	}

	echo implode( str_repeat( '-', 30 )."\r\n", $display );
}
}

?>

Share this post


Link to post
Share on other sites
MX+

estou de férias quando tiver oportunidade envio o código.

Mas vai provar que com php se consegue fazer coisas mais simples com menos código :(

Cumprimentos

Share this post


Link to post
Share on other sites
Betovsky

Welele!!! Demorou mas aqui está  :(

rssgetterer7.th.jpg

Sim o DOS é rabeta...

Aqui fica o código.

import Prelude hiding (catch)
import Network (connectTo, withSocketsDo, PortID(..))
import System.IO
import System.IO.Error (isEOFError)
import Control.Exception (finally, catch, Exception(..))
import Text.XML.HXT.Arrow


main = withSocketsDo $ do
sock <- connectTo "feeds.feedburner.com" $ PortNumber 80
start sock `catch` procErro `finally` hClose sock
	where
	procErro (IOException e) | isEOFError e = return ()
	procErro e = print e

start h = do 
hSetBuffering h LineBuffering
hPutStr h "GET /revistaprogramar_pdfs?format=xml HTTP/1.0\r\n"
hPutStr h "Host: feeds.feedburner.com\r\n\r\n"
xml <- hGetContents h >>= return . dropWhile ('<'/=)
runX (filtraXML xml) >> return ()

filtraXML xml = 
readString [(a_validate, v_no)] xml	>>>
processChildren ( getChildren3 >>> processItems ) >>>
writeDocument [(a_no_xml_pi, v_1)] "-" >>>
getErrStatus

getChildren3 = getChildren >>> getChildren 

processItems = deep $ 
mudaTexto "title" "\n\nTitulo: " <+>
mudaTexto "link" "Link: " <+>
buscaAttributo "enclosure" "url" "URL: " <+>
buscaAttributo "enclosure" "length" "Tamanho: " <+>
buscaAttributo "enclosure" "type" "Tipo: " 

mudaTexto nome header = 
getChildren >>>
isElem >>> hasName nome >>> getChildren >>> 
getText >>> arr (\s -> header ++ s ++ "\n") >>> mkText

buscaAttributo nomeElem nomeAtrib header = 
getChildren >>>
isElem >>> hasName nomeElem >>>
getAttrValue nomeAtrib >>>
arr (\s -> header ++ s ++ "\n") >>>
mkText

Não é a melhor solução, já que estou apenas a transformar o XML. Para ser melhor era usar as Monads do Xml e do IO juntas e fazer os prints à mao. Mas prontos assim também serve...


"Give a man a fish and he will eat for a day; Teach a man to fish and he will eat for a lifetime. The moral? READ THE MANUAL !"

Sign on a computer system consultant's desk

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.