summaryrefslogblamecommitdiffstats
path: root/rtv4d-dl.c
blob: aab20a630ba00504159879b971ca017c5ceb70e8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491










































































































































































































































































































































































































































































































                                                                                                                                                                                                                    
#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; 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 "ToJeMogočeBackdoor!"
#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

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 protokol ni HTTP oziroma URL ni pravilen");
		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;
	char * metakeys[] = {"\"title\"", "\"showId\"", "\"genre\"", \
		"\"showDescription\"", "\"duration\"", "\"jwt\"", "\"showName\"", \
		"\"source\"", "\"publishDate\"", "\"mediaType\"", "\"orig\"", \
		"\"broadcastDate\"", /* sedaj pa za getMedia query */ "\"http\"" };
	char * cp;
#define RTV_META_IZPOLNI_METAKEYS_SIZEOF 12 /* hkrati offset za getMedia */
#define RTV_META_IZPOLNI_METAKEYS_GETMEDIA_FINAL \
	(RTV_META_IZPOLNI_METAKEYS_SIZEOF)+1 /* 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) \
						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."); \
						} else { \
							oblika(imem, format, tip) \
							RTV_NAPISI(HROSC, "Shranil metapodatek " #imem ": %" #format, \
									m->imem); \
						}
#pragma GCC diagnostic ignored "-Wint-conversion" /* macro dela strcpy na str */
						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: /* showDescription */
						RTV_META_IZPOLNI(opis, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 4: /* 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 5: /* 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 6: /* showName */
						RTV_META_IZPOLNI(tip_oddaje_ime, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 7: /* source */
						RTV_META_IZPOLNI(program, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 8: /* publishDate */
						RTV_META_IZPOLNI(objavljeno, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 9: /* mediaType */
						if (RTV_META_IZPOLNI_VALUE[0] == 'v') {
							m->tip_posnetka = RTV_VIDEO_TIP;
						} else {
							m->tip_posnetka = RTV_NEPOZNAN_TIP;
						}
						break;
					case 10: /* orig */ /* sličica */
						RTV_META_IZPOLNI(slicica, RTV_META_IZPOLNI_V, s, '"', char);
						break;
					case 11: /* broadcastDate */
						RTV_META_IZPOLNI(predvajano, RTV_META_IZPOLNI_V, s, '"', char);
						break;
#pragma GCC diagnostic warning "-Wint-conversion" /* smo prej izključili */
					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);
	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);
						break;
					default:
						RTV_NAPISI(OPOZORILO, "Doseg nedefinirane kode!");
				}
			}
		}
	}

	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': /* test - program se preizkusi brez prenosa datotek */
			RTV_NAPISI(NAPAKA, "samotestiranje še ni izdelano!");
			break;
		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': /* 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\nget_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":"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 */
			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;
		default:
			fprintf(stderr, "opcija ne obstaja! poskusi test.\n");
			returnstatus = 2;
			goto returncleanly;
			break;
	}
	returncleanly:
	meta_oddaja_free(m);
	m = NULL;
	return returnstatus;
}