summaryrefslogblamecommitdiffstats
path: root/rtv4d-dl.c
blob: 93ad91907a30590911df22d46aaff2f781b8c091 (plain) (tree)









































                                                                                                                                                          
                                                                           






                                                                                     
                                                                                 








                                                                              
                       
























                                                                                       
                                                                             





























































                                                                                                                                                                                                                    
                                                           



























































































                                                                                          
                                                                                    
                                                                      


                                                                                        
                                                    
                  
                                                                           
                                                  
                                                                       






























                                                                                                                   
                                                                                                              

                                                                                                                     
                                                                                                                          



                                                                                                                       

                                                                                 








                                                                                                                          
                                                                 

                                                                                                         





                                                                                                                 





                                                                                                                    
                                                         




                                                                                                                           
                                                              

                                                                                                                   
                                                            

                                                                                                            
                                                                 

                                                                                                               










                                                                                                   

                                                      
                                                                          

                                                                                                            
                                                                    

                                                                                                               
                                                                  














                                                                                                  







                                                                                     






                                                                                                                 




                                                                                                                      
                                                      

                                                                                 

                                                                                                                  



                                                                                                         



                                                                                                                              
                                                 




                                                                                                            
                                                      
                                                

                                                                                                          


                                 

                                                              





























                                                                                                              
                         


                                                                                
                         
























                                                                                                   
                         




















                                                                                                         
                                                                                                        


                                                                                                     


                                                                                                              



                                                                                                
                         























                                                                                                   




                                                                                          










                                                                              
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <tcp.c>
#define NIZ_DODATEK(a) #a
#define NIZ(a) NIZ_DODATEK(a)
#define RTV_CLIENT_ID "82013fb3a531d5414f478747c1aca622" /* enak za vse */
#define RTV_CLIENT_ID_SIZEOF 32+1
#define RTV_VIDEO_TIP 1
#define RTV_AUDIO_TIP 2
#define RTV_NEPOZNAN_TIP 0
#define RTV_NACIN argv[1]
#define RTV_URL argv[2]
#define RTV_P_SIZEOF 128 /* privzeti sizeof */
#define RTV_TEST_NASLOV "Vreme ob 22h"
#define RTV_TEST_ZANRI "\"INFORMATIVNE VSEBINE\"," \
	"\"DNEVNO INFORMATIVNE ODDAJE\",\"Vremenska poročila\""
#define RTV_TEST_OPIS "Vreme je na sporedu vsak dan po Poročilih, pred in po" \
	" Dnevniku ter po Odmevih. Napoved vremena pa vas čaka tudi vsak delavnik" \
	"	zjutraj v rubriki oddaje Dobro jutro. \\r\\n"
#define RTV_TEST_ID 89614963
#define RTV_TEST_DOLZINA 155
#define RTV_TEST_TIP_ODDAJE_IME "Vreme"
#define RTV_TEST_TIP_ODDAJE_ID 608
#define RTV_TEST_PROGRAM "SLO1"
#define RTV_TEST_OBJAVLJENO "2010-12-03 23:20:10"
#define RTV_TEST_PREDVAJANO "2010-12-03 23:20:10"
#define RTV_TEST_TIP_POSNETKA 4D_VIDEO_TIP
#define RTV_TEST_SLICICA "http://img.rtvslo.si/_up/ava/ava_misc/show_logos" \
	"/VREME_VECERNO-980.jpg"
#define RTV_TEST_KONTROLNA_VREDNOST 1186735842
#define RTV_TEST_VELIKOST 9396765
#define RTV_NAPISI_NAPAKA 1
#define RTV_NAPISI_INFO 1
#define RTV_NAPISI_OPOZORILO 1
#define RTV_NAPISI_HROSC 1
#define RTV_NAPISI(kaj, frmt, ...) /* pazi na format string RCE! */ \
	do { if ( RTV_NAPISI_ ##kaj ) fprintf(stderr, \
													"[" #kaj "] %s@%s:" NIZ(__LINE__) " " frmt "\n", \
													__func__, __FILE__, ##__VA_ARGS__ ); } while(0);
#define RTV_USER_AGENT "Mozilla/5.0 equivalent (rtv4d-dl " RTV_VER "; C " \
	NIZ(__STDC_VERSION__)	" GCC " __VERSION__ "; " __DATE__ " " __TIME__ "; " \
	__FILE__ ":" NIZ(__LINE__) ")"
#define RTV_HTTP_GET \
	"GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: " RTV_USER_AGENT \
	"\r\nAccept: */*\r\nX-Requested-With: tcp.c (" __FILE__ ":" NIZ(__LINE__) \
	")\r\nConnection: close\r\n\r\n"
#define RTV_HTTP_TIMEOUT 69 /* sekund */
#define RTV_NE_BO_POSLAL NULL /* "ToJeMogočeBackdoor!" */ /* bere več znakov */
#define RTV_API_META_URL "http://api.rtvslo.si/ava/getRecordingDrm/" \
	"%u?client_id=" RTV_CLIENT_ID
#define RTV_API_META_URL_SIZEOF 128 /* vključno z nul znakom */
#define RTV_API_MEDIA_URL "http://api.rtvslo.si/ava/getMedia/%u/?client_id=" \
	RTV_CLIENT_ID "&jwt=%s"
#define RTV_API_MEDIA_URL_SIZEOF 64 + RTV_CLIENT_ID_SIZEOF + RTV_JWT_SIZEOF
#define RTV_JWT_SIZEOF 43+1
#define RTV_PREDVAJALNIK_URL "http://4d.rtvslo.si/arhiv/v/%u"
#define RTV_PREDVAJALNIK_URL_SIZEOF 32+1 + 12
#define RTV_VER "0.0.3"

struct meta_oddaja {
	size_t naslov_sizeof;
	char * naslov; /* Vreme ob 22h */
	unsigned int tip_oddaje_id; /* 608 */
	size_t zanri_sizeof; 
	char * zanri; /* INFORMATIVNE VSEBINE, DNEVNO INFORMATIVNE ODDAJE, Vrem... */
	size_t opis_sizeof;
	char * opis; /* Vreme je na sporedu vsak dan po Poročilih, pred in po Dn... */
	unsigned int id; /* 89614963 */
	unsigned int dolzina; /* 155 */
	size_t jwt_sizeof; /* 44 */
	char * jwt; /* 1lKYcP7j8iNwqVQeQC8htsrBN47LpiHq3sm5bFlxRys */
	size_t tip_oddaje_ime_sizeof;
	char * tip_oddaje_ime; /* Vreme */
	size_t program_sizeof;
	char * program; /* SLO1 */
	size_t objavljeno_sizeof;
	char * objavljeno; /* 2010-12-03 23:20:10 */
	unsigned short int tip_posnetka; /* RTV_VIDEO_TIP */
	size_t slicica_sizeof;
	char * slicica; /* http://img.rtvslo.si/_up/ava/ava_misc/show_logos/VREM... */
	size_t predvajano_sizeof;
	char * predvajano; /* 2010-12-03 23:20:10 */
	/* unsigned long long int kontrolna_vrednost; */
	/* unsigned long long int velikost; */ /* število bajtov posnetka */
	char get_meta_url[RTV_API_META_URL_SIZEOF]; /* http://api.rtvslo.si/ava/... */
	char get_media_url[RTV_API_MEDIA_URL_SIZEOF]; /* http://api.rtvslo.si/av... */
	char predvajalnik_url[RTV_PREDVAJALNIK_URL_SIZEOF]; /* http://4d.rtvslo.... */
	size_t posnetek_url_sizeof;
	char * posnetek_url; /* http://progressive.rtvslo.si/encrypted00/2010/12... */
};
struct meta_oddaja * meta_oddaja_alloc () {
	struct meta_oddaja * m = malloc(sizeof(struct meta_oddaja));
	m->naslov = malloc(sizeof(char)*RTV_P_SIZEOF);m->naslov_sizeof = RTV_P_SIZEOF;
	m->zanri = malloc(sizeof(char)*RTV_P_SIZEOF);	m->zanri_sizeof = RTV_P_SIZEOF;
	m->opis = malloc(sizeof(char)*RTV_P_SIZEOF);		m->opis_sizeof = RTV_P_SIZEOF;
	m->tip_oddaje_ime=malloc(sizeof(char)*RTV_P_SIZEOF);
																				m->tip_oddaje_ime_sizeof = RTV_P_SIZEOF;
	m->program = malloc(sizeof(char)*RTV_P_SIZEOF);m->program_sizeof=RTV_P_SIZEOF;
	m->slicica = malloc(sizeof(char)*RTV_P_SIZEOF);m->slicica_sizeof=RTV_P_SIZEOF;
	m->jwt = malloc(sizeof(char)*RTV_P_SIZEOF);		m->jwt_sizeof=RTV_P_SIZEOF;
	m->objavljeno = malloc(sizeof(char)*RTV_P_SIZEOF);
																						m->objavljeno_sizeof = RTV_P_SIZEOF;
	m->predvajano = malloc(sizeof(char)*RTV_P_SIZEOF);
																						m->predvajano_sizeof = RTV_P_SIZEOF;
	m->posnetek_url = malloc(sizeof(char)*RTV_P_SIZEOF);
																					m->posnetek_url_sizeof = RTV_P_SIZEOF;
	return m;
}
int meta_oddaja_free (struct meta_oddaja * m) {
	free(m->naslov);					m->naslov = NULL;
	free(m->zanri);						m->zanri = NULL;
	free(m->opis);						m->opis = NULL;
	free(m->tip_oddaje_ime);	m->tip_oddaje_ime = NULL;
	free(m->program);					m->program = NULL;
	free(m->slicica);					m->slicica = NULL;
	free(m->jwt);							m->jwt = NULL;
	free(m->objavljeno);			m->objavljeno = NULL;
	free(m->predvajano);			m->predvajano = NULL;
	free(m->posnetek_url);		m->posnetek_url = NULL;
	free(m);									m = NULL;
	return 0;
}
int niz_realloc (char * s, size_t * v) {
	*v = (*v)*2;
	s = realloc(s, sizeof(char)*(*v));
	return 0;
}
int http_get (/* const */ char * u, FILE * r) { /* url ostane enak */
	unsigned int p = 80; /* HTTP port ^~~~~~~~ glej man open_memstream, fmemopen*/
	char * k; /* označuje konec imena gostitelja */
	char t; /* začasna shramba za končni znak, ko je le-ta null */
	int c = -42069; /* connection descriptor */
	int ret; /* izhodni status write funkcij */
	char * path; /* kaže na path requesta */
	int returnstatus = 0;
	char * header; /* za headerje */
	FILE * headerstream;
	size_t header_sizeof = 0;
	long long int contentlength = -69420;
	char * request_buf; /* za request buffer */
#define RTV_URL_HOST (u+7)
	if (u == NULL) {
		RTV_NAPISI(NAPAKA, "URL je null!");
		return 1;
	}
	if (strncmp(u, "http://", 7) != 0) {
		RTV_NAPISI(NAPAKA, "URL ni podprt: %s", u);
		return 2;
	}
	k = strchr(RTV_URL_HOST, '/');
	if (k - strchrnul(RTV_URL_HOST, ':') > 0) { /* pred pathom je PORT */
		k = strchrnul(RTV_URL_HOST, ':');
		p = atoi(k+1);
	}
	if (p > 65535) { /* port je nepodpisan, če gre v minus bo itak ZELO > 65535 */
		RTV_NAPISI(NAPAKA, "port je neveljaven");
		return 3;
	}
	if (k == NULL)
		k = strchrnul(RTV_URL_HOST, '/');
	path = strchr(RTV_URL_HOST, '/');
	if (path == NULL) {
		u[6] = '\0'; /* na koncu popravimo nazaj, izkoristimo ta memory xD */
		path = u+5;
	} else {
		path++;
	}
	t = *k;
	*k = '\0';
	RTV_NAPISI(INFO, "Vzpostavljam TCP povezavo na http://%s:%d ...",
			RTV_URL_HOST, p);
	c = spawn_conn(RTV_URL_HOST, p);
	if (c < 0) {
		RTV_NAPISI(NAPAKA, "TCP povezava ni uspela!");
		returnstatus = 4;
		goto http_get_returncleanly;
	} else {
		RTV_NAPISI(INFO, "Povezan na strežnik.");
	}
	request_buf = malloc (sizeof(char) * ( sizeof(RTV_HTTP_GET)
				+ strlen(RTV_URL_HOST)+ strlen(path) + 1 ));
	sprintf(request_buf, RTV_HTTP_GET, path, RTV_URL_HOST); /* =dovolj prostora */
	RTV_NAPISI(INFO, "Pošiljam %lu bajtov ...", strlen(request_buf));
	ret = sync_write(c, request_buf, strlen(request_buf), RTV_HTTP_TIMEOUT);
	if (ret != 0) {
		returnstatus = 5;
		RTV_NAPISI(NAPAKA, "TCP časovna omejitev pri pošiljanju je potekla");
		goto http_get_returncleanly;
	} else {
		RTV_NAPISI(INFO, "Uspešno poslano.");
	}
	headerstream = open_memstream(&header, &header_sizeof);
	while (1) {
		rewind(headerstream);
		ret = read_until(c, headerstream, RTV_HTTP_TIMEOUT, "\n", -1); /* unsig!*/
		fflush(headerstream);
		if (ret != 0) {
			returnstatus = 6;
			RTV_NAPISI(NAPAKA, "Branje headerja ni uspelo!");
			goto http_get_returncleanly;
		}
		if (strncasecmp("Content-Length: ", header, strlen("Content-Length: "))
					== 0) {
			contentlength = strtoll(header+16, NULL, 10);
			RTV_NAPISI(INFO, "Pridobil %lld bajtni odgovor.", contentlength);
		}
		if (strncmp("\r\n", header, 2) == 0 || header[0] == '\n')
			break;
	}
	if (contentlength == -69420) {
		RTV_NAPISI(OPOZORILO, "Manjka Content-Length, berem do konca.");
	} else {
		RTV_NAPISI(INFO, "Začetek telesa odgovora. Berem in pišem.");
	}
	fclose(headerstream);
	ret = read_until(c, r, RTV_HTTP_TIMEOUT, RTV_NE_BO_POSLAL, contentlength);
	if (ret != 0) {
		returnstatus = 7;
		RTV_NAPISI(NAPAKA, "Branje in pisanje telesa odgovora ni uspelo!");
		goto http_get_returncleanly;
	}
	RTV_NAPISI(INFO, "Prejel in uspešno shranil/prebral HTTP odgovor.");
	http_get_returncleanly:
	free(request_buf);
	request_buf = NULL;
	free(header);
	header = NULL;
	if(c != -69420 && kill_conn(c) < 0) /* kill_conn se ne izvede, če prvi ni 1.*/
		RTV_NAPISI(OPOZORILO, "TCP povezave ni uspelo prekiniti");
	*k = t;
	u[6] = '/';
	return returnstatus;
}
int rtv_meta_izpolni(struct meta_oddaja * m) {
	int returnstatus = 0;
	FILE * odgstream;
	char * odg;
	size_t sizeloc;
	size_t i, j;
	unsigned short int nasel_addaptivemedia = 0; /* glej iskanje stream URLja */
	char * metakeys[] = {"\"title\"", "\"showId\"", "\"genre\"", \
		"\"description\"", "\"showDescription\"", "\"duration\"", "\"jwt\"", \
		"\"showName\"",	"\"source\"", "\"publishDate\"", "\"mediaType\"", \
	 	"\"orig\"",	"\"broadcastDate\"", /* getMedia query: */ "\"http\"", \
	 	"\"https\"", "\"addaptiveMedia\"" };
	char * cp;
#define RTV_META_IZPOLNI_METAKEYS_SIZEOF 13 /* hkrati offset za getMedia */
#define RTV_META_IZPOLNI_METAKEYS_GETMEDIA_FINAL \
	(RTV_META_IZPOLNI_METAKEYS_SIZEOF+3) /* zadnji+1 za getMedia */
#define RTV_META_IZPOLNI_VALUE (odg+i+strlen(metakeys[j])+2)
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE
	snprintf(m->get_meta_url, RTV_API_META_URL_SIZEOF, RTV_API_META_URL, m->id);
	snprintf(m->predvajalnik_url, RTV_PREDVAJALNIK_URL_SIZEOF, RTV_PREDVAJALNIK_URL, m->id);
	odgstream = open_memstream(&odg, &sizeloc);
	returnstatus = http_get(m->get_meta_url, odgstream); /* shranimo metapodat. */
	if (returnstatus != 0) {
		RTV_NAPISI(NAPAKA, "Zahteva za metapodatke iz API strežnika je spodletela");
		goto rtv_meta_izpolni_returncleanly;
	}
	fflush(odgstream);
	for (i = 0; i < sizeloc; i++) {
		for (j = 0; j < RTV_META_IZPOLNI_METAKEYS_SIZEOF; j++) {
			if (strncmp(odg+i, metakeys[j], strlen(metakeys[j])) == 0) {
				switch (j) {
					case 0: /* title */
#define strtollu strtoull
#define strtolu strtoul
#define strtolld strtoll
#define strtold strtol
#define strtod strtol
#define strtou strtoul
#define RTV_META_IZPOLNI_V(imem, format, tip) /* za variabilne nize */ \
						cp[0] = '\0'; /* omejimo json string, ne potrebujemo strncpy */ \
						m->imem = realloc(m->imem, sizeof(tip) * \
								strlen(RTV_META_IZPOLNI_VALUE_INTERNAL)+1); \
						m->imem##_sizeof = strlen(RTV_META_IZPOLNI_VALUE_INTERNAL)+1; \
						strcpy(m->imem, RTV_META_IZPOLNI_VALUE_INTERNAL);
#define RTV_META_IZPOLNI_I(imem, format, tip) /* za številke */ \
						m->imem = strto##format(RTV_META_IZPOLNI_VALUE_INTERNAL, NULL, 10);
#define RTV_META_IZPOLNI(imem, oblika, format, splitter, tip) \
						do { cp = strchr(RTV_META_IZPOLNI_VALUE_INTERNAL, splitter); \
						if (cp == NULL) { \
							RTV_NAPISI(OPOZORILO, "Napaka pri iskanju podatka " #imem); \
							/* strcpy(m->imem, "Napaka pri pridobivanju."); */ /* ni vse s*/ \
						} else { \
							oblika(imem, format, tip) \
							RTV_NAPISI(HROSC, "Shranil metapodatek " #imem ": %" #format, \
									m->imem); \
						} } while (0)
/* #pragma GCC diagnostic ignored "-Wint-conversion" */ /* surpressaš opozor. */
						RTV_META_IZPOLNI(naslov, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 1: /* showId */
						RTV_META_IZPOLNI(tip_oddaje_id, RTV_META_IZPOLNI_I, u, '"', unsigned int);
						break;
					case 2: /* genre je "asdasd","asdasd","sdfsfd" */
						RTV_META_IZPOLNI(zanri, RTV_META_IZPOLNI_V, s, ']', char);
						memmove(m->zanri, (m->zanri)+1, strlen(m->zanri)+1);
						break;
					case 3: /* description */
						RTV_META_IZPOLNI(opis, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 4: /* showDescription */
						if (m->opis[0] == '\0') { /* če je prejšnji spodletel */
							RTV_META_IZPOLNI(opis, RTV_META_IZPOLNI_V, s, '"', char);
						}
						break;
					case 5: /* duration */
#undef RTV_META_IZPOLNI_VALUE_INTERNAL
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE-1
						RTV_META_IZPOLNI(dolzina, RTV_META_IZPOLNI_I, u, '"', unsigned int);
#undef RTV_META_IZPOLNI_VALUE_INTERNAL
#define RTV_META_IZPOLNI_VALUE_INTERNAL RTV_META_IZPOLNI_VALUE
						break;
					case 6: /* jwt */
						RTV_META_IZPOLNI(jwt, RTV_META_IZPOLNI_V, s, '"', char);
						if (RTV_JWT_SIZEOF != m->jwt_sizeof) {
							RTV_NAPISI(OPOZORILO, "Shranil nepričakovano dolg JWT! Je vdor?");
						}
						break;
					case 7: /* showName */
						RTV_META_IZPOLNI(tip_oddaje_ime, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 8: /* source */
						RTV_META_IZPOLNI(program, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 9: /* publishDate */
						RTV_META_IZPOLNI(objavljeno, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 10: /* mediaType */
						switch (RTV_META_IZPOLNI_VALUE[0]) {
							case 'v':
								m->tip_posnetka = RTV_VIDEO_TIP;
								break;
							case 'a':
								m->tip_posnetka = RTV_AUDIO_TIP;
								break;
							default:
								m->tip_posnetka = RTV_NEPOZNAN_TIP;
								break;
						}
						break;
					case 11: /* orig */ /* sličica */
						RTV_META_IZPOLNI(slicica, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 12: /* broadcastDate */
						RTV_META_IZPOLNI(predvajano, RTV_META_IZPOLNI_V, s, '"', char);
						break;
/* #pragma GCC diagnostic warning "-Wint-conversion" */ /* undo */
					default:
						RTV_NAPISI(OPOZORILO, "Doseg nedefinirane kode!");
				}
			}
		}
	}
	snprintf(m->get_media_url, RTV_API_MEDIA_URL_SIZEOF, RTV_API_MEDIA_URL, m->id, m->jwt);
	rewind(odgstream);
	fflush(odgstream);
	returnstatus = http_get(m->get_media_url, odgstream); /* shranimo video url */
	if (returnstatus != 0) {
		RTV_NAPISI(NAPAKA, "Zahteva za ključ videa iz API strežnika je spodletela");
		goto rtv_meta_izpolni_returncleanly;
	}
	fflush(odgstream);
	/*
	 * sedaj pridobimo direktni URL do mp4 datoteke, ki ima keylockhash v GET
	 * parametru. OPOMBA: treba je najti NAJKVALITETNEJŠO datoteko, ker RTVSLO
	 * strežnik pošilja zmešan vrstni red JSON parametrov, bo treba najti drug
	 * način. ugotovil sem, da, če je stream v addaptiveMedia JSON podobjektu,
	 * bo ta vedno največji, če pa obstaja samo en stream, pa addaptiveMedia
	 * podobjekta sploh ne bo. torej, če se je string addaptiveMedia pojavil
	 * tik pred tem URLjem, bo ta najboljši in lahko nehamo. */
	for (i = 0; i < ftell(odgstream); i++) {
		for (j = RTV_META_IZPOLNI_METAKEYS_SIZEOF;
				j < RTV_META_IZPOLNI_METAKEYS_GETMEDIA_FINAL; j++) {
			if (strncmp(odg+i, metakeys[j], strlen(metakeys[j])) == 0) {
				switch (j-RTV_META_IZPOLNI_METAKEYS_SIZEOF) {
					case 0: /* http */ /* videofile */
						RTV_META_IZPOLNI(posnetek_url, RTV_META_IZPOLNI_V, s, '"', char);
						if (nasel_addaptivemedia == 1) {
							RTV_NAPISI(HROSC, "Izmed več streamov izbral najboljšega.");
							goto rtv_meta_izpolni_naselnajboljsistream;
						}
						nasel_addaptivemedia = 0;
						break;
					case 1: /* https */
						if (m->posnetek_url[0] == '\0') {
							RTV_META_IZPOLNI(posnetek_url, RTV_META_IZPOLNI_V, s, '"',
									char);
							fprintf(stderr, "test: %s\n", m->posnetek_url);
							memmove((m->posnetek_url)+4, (m->posnetek_url)+5,
									strlen((m->posnetek_url)+5)+1);
							RTV_NAPISI(HROSC, "Popravil HTTPS URL na HTTP");
							if (nasel_addaptivemedia == 1) {
								RTV_NAPISI(HROSC, "Izmed več streamov izbral najboljšega.");
								goto rtv_meta_izpolni_naselnajboljsistream;
							}
						}
						nasel_addaptivemedia = 0;
						break;
					case 2: /* addaptiveMedia */
						nasel_addaptivemedia = 1;
						RTV_NAPISI(HROSC, "Naslednji najden pretok bo najboljši.");
						break;
					default:
						RTV_NAPISI(OPOZORILO, "Doseg nedefinirane kode; case=%lu",
								j-RTV_META_IZPOLNI_METAKEYS_SIZEOF);
				}
			}
		}
	} /* endfor: for (i = 0; i < ftell(odgstream); i++) */
	rtv_meta_izpolni_naselnajboljsistream:

	rtv_meta_izpolni_returncleanly:
	fclose(odgstream);
	free(odg);
	odg = NULL;
	return returnstatus;
}
int main (int argc, char ** argv) {
	if (argc < 1+1) {
		fprintf(stderr, "preberi README.md pred uporabo programa, saj vsebuje navodila in ostalo.\n");
		return 1;
	}
	struct meta_oddaja * m = meta_oddaja_alloc();
	char fn[69]; /* <id>.txt / <id>.mp4 - NE USER INPUT */
	char * e; /* char pointer for the memes */
	FILE * fd;
	unsigned short int returnstatus = 0;
	if (RTV_URL != NULL) {
		m->id = atoi(RTV_URL);
		if (strrchr(RTV_URL, '/') != NULL)
			m->id = atoi(strrchr(RTV_URL, '/')+1);
		if (m->id <= 0) {
			fprintf(stderr, "IDja oddaje ni uspelo dobiti. preverite vnos.\n");
			returnstatus = 3;
			goto returncleanly;
		}
	} else {
		m->id = RTV_TEST_ID;
	}
	switch (RTV_NACIN[0]) {
		case 'T':
		case 't': /* test - program se preizkusi brez prenosa datotek */
			RTV_NAPISI(NAPAKA, "samotestiranje še ni izdelano!");
			break;
		case 'O':
		case 'o': /* oddaja - prenese oddajo v datoteko */
			if (rtv_meta_izpolni(m) != 0) {
				RTV_NAPISI(NAPAKA, "Ni uspelo pridobiti metapodatkov oddaje.");
				returnstatus = 4;
				goto returncleanly;
			}
			if (argc < 4) {
				e = strrchr(m->posnetek_url, '.');
				snprintf(fn, 68, "%u%.4s", m->id, e);
				fd = fopen(fn, "w");
			} else {
				fd = fopen(argv[3], "w");
			}
			if (fd == NULL) {
				RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo.");
				returnstatus = 5;
				goto returncleanly;
			}
			if (http_get(m->posnetek_url, fd) == 0) {
				RTV_NAPISI(INFO, "uspešno shranjeno.");	
			} else {
				RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()");
				returnstatus = 6;
			}
			break;
		case 'M':
		case 'm': /* meta-oddaja - prenese metapodatke o oddaji */
			if (rtv_meta_izpolni(m) != 0) {
				RTV_NAPISI(NAPAKA, "Ni uspelo pridobiti metapodatkov oddaje.");
				returnstatus = 4;
				goto returncleanly;
			}
			if (argc < 4) {
				/* e = strrchr(m->posnetek_url, '.'); */
				snprintf(fn, 68, "%u%s", m->id, ".txt");
				fd = fopen(fn, "w");
			} else {
				fd = fopen(argv[3], "w");
			}
			if (fd == NULL) {
				RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo.");
				returnstatus = 5;
				goto returncleanly;
			}
			fprintf(fd, "id: %u\nnaslov: %s\ntip_oddaje_id: %u\nzanri: %s\nopis: %s\n"
					"dolzina: %u\njwt: %s\ntip_oddaje_ime: %s\nprogram: %s\n"
					"objavljeno: %s\ntip_posnetka: %s\nslicica: %s\npredvajano: %s\n"
					/* "velikost: %llu\n" */ "get_meta_url: %s\nget_media_url: %s\n"
					"predvajalnik_url: %s\nposnetek_url: %s\n", m->id, m->naslov,
					m->tip_oddaje_id, m->zanri, m->opis, m->dolzina, m->jwt,
					m->tip_oddaje_ime, m->program, m->objavljeno,
				 	m->tip_posnetka == RTV_VIDEO_TIP ? "RTV_VIDEO_TIP" : \
					m->tip_posnetka == RTV_AUDIO_TIP ? "RTV_AUDIO_TIP":"RTV_NEPOZNAN_TIP",
					m->slicica, m->predvajano, /* m->velikost, */ m->get_meta_url,
					m->get_media_url, m->predvajalnik_url, m->posnetek_url);
			fclose(fd);
			break;
		case 's': /* sličica - prenese sličico oddaje */
		case 'S':
			if (rtv_meta_izpolni(m) != 0) {
				RTV_NAPISI(NAPAKA, "Ni uspelo pridobiti metapodatkov oddaje.");
				returnstatus = 4;
				goto returncleanly;
			}
			if (argc < 4) {
				e = strrchr(m->slicica, '.');
				snprintf(fn, 68, "%u%.4s", m->id, e);
				fd = fopen(fn, "w");
			} else {
				fd = fopen(argv[3], "w");
			}
			if (fd == NULL) {
				RTV_NAPISI(NAPAKA, "Ni uspelo odpreti datoteke za pisanje vanjo.");
				returnstatus = 5;
				goto returncleanly;
			}
			if (http_get(m->slicica, fd) == 0) {
				RTV_NAPISI(INFO, "uspešno shranjeno.");	
			} else {
				RTV_NAPISI(NAPAKA, "Nekaj je spodletelo pri http_get()");
				returnstatus = 6;
			}
			break;
		case 'z': /* zivo */
		case 'Z':
		case 0xC5: /* živo / Živo, ž = 0xc5be, Ž = 0xc5bd, tudi šivo dela! */
			RTV_NAPISI(NAPAKA, "pretakanje v živo še ni izdelano!");
			break;
		default:
			fprintf(stderr, "opcija ne obstaja! poskusi test.\n");
			returnstatus = 2;
			goto returncleanly;
			break;
	}
	returncleanly:
	meta_oddaja_free(m);
	m = NULL;
	return returnstatus;
}