github.ccut.club/rafael-santiago/cherry@v0.0.0-20161214151746-8ea42c6e9670/src/pkg/config/parser/parser.go (about) 1 /* 2 Package parser parse and loads a cherry file to the memory. 3 -- 4 * Copyright (C) 2015 by Rafael Santiago 5 * 6 * This is a free software. You can redistribute it and/or modify under 7 * the terms of the GNU General Public License version 2. 8 * 9 */ 10 package parser 11 12 import ( 13 "fmt" 14 "io/ioutil" 15 "os" 16 "pkg/config" 17 "strconv" 18 "strings" 19 ) 20 21 // CherryFileError is returned by any parse function implemented in "parser.go". 22 type CherryFileError struct { 23 src string 24 line int 25 msg string 26 } 27 28 // Error spits the error string. 29 func (c *CherryFileError) Error() string { 30 if c.line > -1 { 31 return fmt.Sprintf("ERROR: %s: at line %d: %s\n", c.src, c.line, c.msg) 32 } 33 return fmt.Sprintf("ERROR: %s: %s\n", c.src, c.msg) 34 } 35 36 // NewCherryFileError creates a *CherryFileError. 37 func NewCherryFileError(src string, line int, msg string) *CherryFileError { 38 return &CherryFileError{src, line, msg} 39 } 40 41 // GetDataFromSection returns the raw section data from a cherry file section data. 42 func GetDataFromSection(section, configData string, currLine int, currFile string) (string, int, int, *CherryFileError) { 43 var s int 44 var temp string 45 for s = 0; s < len(configData); s++ { 46 switch configData[s] { 47 case '#': 48 for configData[s] != '\n' && configData[s] != '\r' && s < len(configData) { 49 s++ 50 } 51 if s < len(configData) { 52 currLine++ 53 } 54 continue 55 case '(', '\n', ' ', '\t', '\r': 56 if configData[s] == '\n' { 57 currLine++ 58 } 59 if temp == section { 60 if configData[s] == '\n' || configData[s] == '\r' || configData[s] == ' ' || configData[s] == '\t' { 61 for s < len(configData) && configData[s] != '(' { 62 s++ 63 if s < len(configData) && configData[s] == '\n' { 64 currLine++ 65 } 66 } 67 } 68 if s < len(configData) && configData[s] == '(' { 69 s++ 70 } 71 var data string 72 for s < len(configData) { 73 if configData[s] == '"' { 74 data += string(configData[s]) 75 s++ 76 for s < len(configData) && configData[s] != '"' { 77 if configData[s] != '\\' { 78 data += string(configData[s]) 79 } else { 80 data += string(configData[s+1]) 81 s++ 82 } 83 s++ 84 } 85 if s < len(configData) { 86 data += string(configData[s]) 87 } 88 } else if configData[s] != ')' { 89 data += string(configData[s]) 90 } else { 91 break 92 } 93 s++ 94 } 95 return data, s, currLine, nil 96 } else if temp == "cherry.branch" { 97 for s < len(configData) && (configData[s] == ' ' || configData[s] == '\t') { 98 s++ 99 } 100 if s < len(configData) { 101 var branchFilepath string 102 for s < len(configData) && configData[s] != '\n' && configData[s] != '\r' { 103 branchFilepath += string(configData[s]) 104 s++ 105 } 106 if s < len(configData) { 107 currLine++ 108 } 109 branchBuffer, err := ioutil.ReadFile(branchFilepath) 110 if err != nil { 111 fmt.Println(fmt.Sprintf("WARNING: %s: at line %d: %s. Be tidy... removing or commenting this dry branch from your cherry.", currFile, currLine-1, err.Error())) 112 //return "", s, currLine, NewCherryFileError(currFile, 113 // currLine - 1, 114 // "unable to read cherry.branch from \"" + branchFilepath + "\" [ details: " + err.Error() + " ]") 115 } else { 116 branchData, branchOffset, branchLine, _ := GetDataFromSection(section, string(branchBuffer), 1, branchFilepath) 117 if len(branchData) > 0 { 118 return branchData, branchOffset, branchLine, nil 119 } 120 } 121 } 122 } 123 temp = "" 124 break 125 default: 126 temp += string(configData[s]) 127 break 128 } 129 } 130 return "", s, currLine, NewCherryFileError(currFile, -1, "section \""+section+"\" not found.") 131 } 132 133 // GetNextSetFromData returns the next "field = value". 134 func GetNextSetFromData(data string, currLine int, tok string) ([]string, int, string) { 135 if len(data) == 0 { 136 return make([]string, 0), currLine, "" 137 } 138 var s int 139 for s = 0; s < len(data) && (data[s] == ' ' || data[s] == '\t' || data[s] == '\n' || data[s] == '\r'); s++ { 140 if data[s] == '\n' { 141 currLine++ 142 } 143 } 144 var line string 145 for s < len(data) && data[s] != '\n' && data[s] != '\r' { 146 if data[s] == '"' { 147 line += string(data[s]) 148 s++ 149 for s < len(data) && data[s] != '"' { 150 if data[s] == '\\' { 151 s++ 152 } 153 line += string(data[s]) 154 if data[s] == '\n' { 155 currLine++ 156 } 157 s++ 158 } 159 if s < len(data) { 160 line += string(data[s]) 161 } 162 } else if data[s] == '#' { 163 for s < len(data) && data[s] != '\n' { 164 s++ 165 } 166 if s < len(data) { 167 currLine++ 168 } 169 } else { 170 line += string(data[s]) 171 } 172 s++ 173 } 174 if len(line) == 0 { 175 if len(data) == 0 { 176 return make([]string, 0), currLine, "" 177 } 178 } 179 set := strings.Split(line, tok) 180 if len(set) == 2 { 181 set[0] = StripBlanks(set[0]) 182 set[1] = StripBlanks(set[1]) 183 } 184 var nextData string 185 if s < len(data) { 186 nextData = data[s:] 187 } 188 return set, currLine, nextData 189 } 190 191 // StripBlanks strips all blanks. 192 func StripBlanks(data string) string { 193 var retval string 194 var dStart int 195 for dStart < len(data) && (data[dStart] == ' ' || data[dStart] == '\t') { 196 dStart++ 197 } 198 var dEnd = len(data) - 1 199 for dEnd > 0 && (data[dEnd] == ' ' || data[dEnd] == '\t') { 200 dEnd-- 201 } 202 retval = data[dStart : dEnd+1] 203 return retval 204 } 205 206 // ParseCherryFile parses a file at @filepath and returns a *config.CherryRooms or a *CherryFileError. 207 func ParseCherryFile(filepath string) (*config.CherryRooms, *CherryFileError) { 208 var cherryRooms *config.CherryRooms 209 var cherryFileData []byte 210 var data string 211 var err *CherryFileError 212 var line int 213 cherryFileData, ioErr := ioutil.ReadFile(filepath) 214 if ioErr != nil { 215 return nil, NewCherryFileError("(no file)", -1, fmt.Sprintf("unable to read from \"%s\" [more details: %s].", filepath, ioErr.Error())) 216 } 217 data, _, line, err = GetDataFromSection("cherry.root", string(cherryFileData), 1, filepath) 218 if err != nil { 219 return nil, err 220 } 221 var set []string 222 cherryRooms = config.NewCherryRooms() 223 set, line, data = GetNextSetFromData(data, line, "=") 224 for len(set) == 2 { 225 switch set[0] { 226 case "servername", "certificate", "private-key": 227 if set[1][0] != '"' || set[1][len(set[1])-1] != '"' { 228 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("invalid string.")) 229 } 230 data := set[1][1 : len(set[1])-1] 231 232 if set[0] == "certificate" || set[0] == "private-key" { 233 if _, err := os.Stat(data); os.IsNotExist(err) { 234 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("\"%s\" must receive an accessible file path.", set[0])) 235 } 236 } 237 238 if set[0] == "servername" { 239 cherryRooms.SetServername(data) 240 } else if set[0] == "certificate" { 241 cherryRooms.SetCertificatePath(data) 242 } else if set[0] == "private-key" { 243 cherryRooms.SetPrivateKeyPath(data) 244 } 245 break 246 247 default: 248 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("unknown config set \"%s\".", set[0])) 249 } 250 set, line, data = GetNextSetFromData(data, line, "=") 251 } 252 if cherryRooms.GetServername() == "localhost" { 253 fmt.Println("WARN: cherry.root.servername is equals to \"localhost\". Things will not work outside this node.") 254 } 255 data, _, line, err = GetDataFromSection("cherry.rooms", string(cherryFileData), 1, filepath) 256 if err != nil { 257 return nil, err 258 } 259 // INFO(Santiago): Adding all scanned rooms from the first cherry.rooms section found 260 // [cherry branches were scanned too at this point]. 261 set, line, data = GetNextSetFromData(data, line, ":") 262 for len(set) == 2 { 263 if cherryRooms.HasRoom(set[0]) { 264 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("room \"%s\" redeclared.", set[0])) 265 } 266 var value int64 267 var convErr error 268 value, convErr = strconv.ParseInt(set[1], 10, 16) 269 if convErr != nil { 270 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("invalid port value \"%s\" [more details: %s].", set[1], convErr)) 271 } 272 var port int16 273 port = int16(value) 274 if cherryRooms.PortBusyByAnotherRoom(port) { 275 return nil, NewCherryFileError(filepath, line, fmt.Sprintf("the port \"%s\" is already busy by another room.", set[1])) 276 } 277 278 cherryRooms.AddRoom(set[0], port) 279 280 errRoomConfig := GetRoomTemplates(set[0], cherryRooms, string(cherryFileData), filepath) 281 if errRoomConfig != nil { 282 return nil, errRoomConfig 283 } 284 285 errRoomConfig = GetRoomActions(set[0], cherryRooms, string(cherryFileData), filepath) 286 if errRoomConfig != nil { 287 return nil, errRoomConfig 288 } 289 290 // INFO(Santiago): until now these two following sections are non-mandatory. 291 292 _ = GetRoomImages(set[0], cherryRooms, string(cherryFileData), filepath) 293 294 //_ = GetRoomSounds(set[0], cherryRooms, string(cherryFileData), filepath) 295 296 errRoomConfig = GetRoomMisc(set[0], cherryRooms, string(cherryFileData), filepath) 297 if errRoomConfig != nil { 298 return nil, errRoomConfig 299 } 300 301 // INFO(Santiago): Let's transfer the next room from file to the memory. 302 set, line, data = GetNextSetFromData(data, line, ":") 303 } 304 return cherryRooms, nil 305 } 306 307 // GetRoomTemplates parses "cherry.[roomName].templates" section. 308 func GetRoomTemplates(roomName string, cherryRooms *config.CherryRooms, configData, filepath string) *CherryFileError { 309 var data string 310 var line int 311 var err *CherryFileError 312 data, _, line, err = GetDataFromSection("cherry."+roomName+".templates", 313 configData, 1, filepath) 314 if err != nil { 315 return err 316 } 317 var set []string 318 set, line, data = GetNextSetFromData(data, line, "=") 319 for len(set) == 2 { 320 if cherryRooms.HasTemplate(roomName, set[0]) { 321 return NewCherryFileError(filepath, line, "room template \""+set[0]+"\" redeclared.") 322 } 323 if len(set[1]) == 0 { 324 return NewCherryFileError(filepath, line, "room template with no value.") 325 } 326 if set[1][0] != '"' || set[1][len(set[1])-1] != '"' { 327 return NewCherryFileError(filepath, line, "room template must be set with a valid string.") 328 } 329 var templateData []byte 330 var templateDataErr error 331 templateData, templateDataErr = ioutil.ReadFile(set[1][1 : len(set[1])-1]) 332 if templateDataErr != nil { 333 return NewCherryFileError(filepath, line, "unable to access room template file [more details: "+templateDataErr.Error()+"].") 334 } 335 cherryRooms.AddTemplate(roomName, set[0], string(templateData)) 336 set, line, data = GetNextSetFromData(data, line, "=") 337 } 338 return nil 339 } 340 341 // GetRoomActions parses "cherry.[roomName].actions" section. 342 func GetRoomActions(roomName string, cherryRooms *config.CherryRooms, configData, filepath string) *CherryFileError { 343 return getIndirectConfig("cherry."+roomName+".actions", 344 "cherry."+roomName+".actions.templates", 345 roomActionMainVerifier, roomActionSubVerifier, roomActionSetter, 346 roomName, cherryRooms, configData, filepath) 347 } 348 349 // GetRoomImages parses "cherry.[roomName].images" and "cherry.[roomName].images.url". 350 func GetRoomImages(roomName string, cherryRooms *config.CherryRooms, configData, filepath string) *CherryFileError { 351 return getIndirectConfig("cherry."+roomName+".images", 352 "cherry."+roomName+".images.url", 353 roomImageMainVerifier, roomImageSubVerifier, roomImageSetter, 354 roomName, cherryRooms, configData, filepath) 355 } 356 357 //func GetRoomSounds(roomName string, cherryRooms *config.CherryRooms, configData, filepath string) *CherryFileError { 358 // return getIndirectConfig("cherry." + roomName + ".sounds", 359 // "cherry." + roomName + ".sounds.url", 360 // room_sound_main_verifier, room_sound_sub_verifier, room_sound_setter, 361 // roomName, cherryRooms, configData, filepath) 362 //} 363 364 // GetRoomMisc parses "cherry.[roomName].misc" section. 365 func GetRoomMisc(roomName string, cherryRooms *config.CherryRooms, configData, filepath string) *CherryFileError { 366 var mData string 367 var mLine int 368 var mErr *CherryFileError 369 mData, _, mLine, mErr = GetDataFromSection("cherry."+roomName+".misc", configData, 1, filepath) 370 if mErr != nil { 371 return mErr 372 } 373 374 var verifier map[string]func(string) bool 375 verifier = make(map[string]func(string) bool) 376 verifier["join-message"] = verifyString 377 verifier["exit-message"] = verifyString 378 verifier["on-ignore-message"] = verifyString 379 verifier["on-deignore-message"] = verifyString 380 verifier["greeting-message"] = verifyString 381 verifier["private-message-marker"] = verifyString 382 verifier["max-users"] = verifyNumber 383 verifier["allow-brief"] = verifyBool 384 //verifier["flooding-police"] = verifyBool 385 //verifier["max-flood-allowed-before-kick"] = verifyNumber 386 verifier["all-users-alias"] = verifyString 387 verifier["ignore-action"] = verifyString 388 verifier["deignore-action"] = verifyString 389 verifier["public-directory"] = verifyString 390 391 var setter map[string]func(*config.CherryRooms, string, string) 392 setter = make(map[string]func(*config.CherryRooms, string, string)) 393 setter["join-message"] = setJoinMessage 394 setter["exit-message"] = setExitMessage 395 setter["on-ignore-message"] = setOnIgnoreMessage 396 setter["on-deignore-message"] = setOnDeIgnoreMessage 397 setter["greeting-message"] = setGreetingMessage 398 setter["private-message-marker"] = setPrivateMessageMarker 399 setter["max-users"] = setMaxUsers 400 setter["allow-brief"] = setAllowBrief 401 //setter["flooding-police"] = set_flooding_police 402 //setter["max-flood-allowed-before-kick"] = set_max_flood_allowed_before_kick 403 setter["all-users-alias"] = setAllUsersAlias 404 setter["ignore-action"] = setIgnoreAction 405 setter["deignore-action"] = setDeIgnoreAction 406 setter["public-directory"] = setPublicDirectory 407 408 var alreadySet map[string]bool 409 alreadySet = make(map[string]bool) 410 alreadySet["join-message"] = false 411 alreadySet["exit-message"] = false 412 alreadySet["on-ignore-message"] = false 413 alreadySet["on-deignore-message"] = false 414 alreadySet["greeting-message"] = false 415 alreadySet["private-message-marker"] = false 416 alreadySet["max-users"] = false 417 //alreadySet["flooding-police"] = false 418 //alreadySet["max-flood-allowed-before-kick"] = false 419 alreadySet["all-users-alias"] = false 420 alreadySet["ignore-action"] = false 421 alreadySet["deignore-action"] = false 422 alreadySet["public-directory"] = false 423 424 var mSet []string 425 mSet, mLine, mData = GetNextSetFromData(mData, mLine, "=") 426 for len(mSet) == 2 { 427 _, exists := verifier[mSet[0]] 428 if !exists { 429 return NewCherryFileError(filepath, mLine, "misc configuration named as \""+mSet[0]+"\" is unrecognized.") 430 } 431 if alreadySet[mSet[0]] { 432 return NewCherryFileError(filepath, mLine, "misc configuration \""+mSet[0]+"\" re-configured.") 433 } 434 if !verifier[mSet[0]](mSet[1]) { 435 return NewCherryFileError(filepath, mLine, "misc configuration \""+mSet[0]+"\" has invalid value : "+mSet[1]) 436 } 437 setter[mSet[0]](cherryRooms, roomName, mSet[1]) 438 alreadySet[mSet[0]] = true 439 mSet, mLine, mData = GetNextSetFromData(mData, mLine, "=") 440 } 441 442 return nil 443 } 444 445 func setIgnoreAction(cherryRooms *config.CherryRooms, roomName, action string) { 446 cherryRooms.SetIgnoreAction(roomName, action[1:len(action)-1]) 447 } 448 449 func setDeIgnoreAction(cherryRooms *config.CherryRooms, roomName, action string) { 450 cherryRooms.SetDeIgnoreAction(roomName, action[1:len(action)-1]) 451 } 452 453 func setJoinMessage(cherryRooms *config.CherryRooms, roomName, message string) { 454 cherryRooms.SetJoinMessage(roomName, message[1:len(message)-1]) 455 } 456 457 func setExitMessage(cherryRooms *config.CherryRooms, roomName, message string) { 458 cherryRooms.SetExitMessage(roomName, message[1:len(message)-1]) 459 } 460 461 func setOnIgnoreMessage(cherryRooms *config.CherryRooms, roomName, message string) { 462 cherryRooms.SetOnIgnoreMessage(roomName, message[1:len(message)-1]) 463 } 464 465 func setOnDeIgnoreMessage(cherryRooms *config.CherryRooms, roomName, message string) { 466 cherryRooms.SetOnDeIgnoreMessage(roomName, message[1:len(message)-1]) 467 } 468 469 func setGreetingMessage(cherryRooms *config.CherryRooms, roomName, message string) { 470 cherryRooms.SetGreetingMessage(roomName, message[1:len(message)-1]) 471 } 472 473 func setPrivateMessageMarker(cherryRooms *config.CherryRooms, roomName, marker string) { 474 cherryRooms.SetPrivateMessageMarker(roomName, marker[1:len(marker)-1]) 475 } 476 477 func setMaxUsers(cherryRooms *config.CherryRooms, roomName, value string) { 478 var intValue int64 479 intValue, _ = strconv.ParseInt(value, 10, 64) 480 cherryRooms.SetMaxUsers(roomName, int(intValue)) 481 } 482 483 func setAllowBrief(cherryRooms *config.CherryRooms, roomName, value string) { 484 var allow bool 485 allow = (value == "yes" || value == "true") 486 cherryRooms.SetAllowBrief(roomName, allow) 487 } 488 489 func setPublicDirectory(cherryRooms *config.CherryRooms, roomName, value string) { 490 cherryRooms.SetPublicDirectory(roomName, value[1:len(value)-1]) 491 } 492 493 //func set_flooding_police(cherryRooms *config.CherryRooms, roomName, value string) { 494 // var impose bool 495 // impose = (value == "yes") 496 // cherryRooms.SetFloodingPolice(roomName, impose) 497 //} 498 499 func setAllUsersAlias(cherryRooms *config.CherryRooms, roomName, value string) { 500 cherryRooms.SetAllUsersAlias(roomName, value[1:len(value)-1]) 501 } 502 503 //func set_max_flood_allowed_before_kick(cherryRooms *config.CherryRooms, roomName, value string) { 504 // var intValue int64 505 // intValue, _ = strconv.ParseInt(value, 10, 64) 506 // cherryRooms.SetMaxFloodAllowedBeforeKick(roomName, int(intValue)) 507 //} 508 509 func verifyNumber(buffer string) bool { 510 if len(buffer) == 0 { 511 return false 512 } 513 for _, b := range buffer { 514 if b != '0' && 515 b != '1' && 516 b != '2' && 517 b != '3' && 518 b != '4' && 519 b != '5' && 520 b != '6' && 521 b != '7' && 522 b != '8' && 523 b != '9' { 524 return false 525 } 526 } 527 return true 528 } 529 530 func verifyString(buffer string) bool { 531 if len(buffer) <= 1 { 532 return false 533 } 534 return (buffer[0] == '"' && buffer[len(buffer)-1] == '"') 535 } 536 537 func verifyBool(buffer string) bool { 538 if len(buffer) == 0 { 539 return false 540 } 541 return (buffer == "yes" || buffer == "no" || buffer == "true" || buffer == "false") 542 } 543 544 // WARN(Santiago): The following codes are a brain damage. I am sorry. 545 546 func getIndirectConfig(mainSection, 547 subSection string, 548 mainVerifier, 549 subVerifier func([]string, []string, int, int, string, string, *config.CherryRooms) *CherryFileError, 550 setter func(*config.CherryRooms, string, []string, []string), 551 roomName string, 552 cherryRooms *config.CherryRooms, 553 configData, 554 filepath string) *CherryFileError { 555 var mData string 556 var mLine int 557 var mErr *CherryFileError 558 mData, _, mLine, mErr = GetDataFromSection(mainSection, configData, 1, filepath) 559 if mErr != nil { 560 return mErr 561 } 562 563 var sData string 564 var sLine int 565 var sErr *CherryFileError 566 sData, _, sLine, sErr = GetDataFromSection(subSection, configData, 1, filepath) 567 568 if sErr != nil { 569 return sErr 570 } 571 572 var mSet []string 573 mSet, mLine, mData = GetNextSetFromData(mData, mLine, "=") 574 for len(mSet) == 2 { 575 var sSet []string 576 mErr = mainVerifier(mSet, sSet, mLine, sLine, roomName, filepath, cherryRooms) 577 if mErr != nil { 578 return mErr 579 } 580 581 // INFO(Santiago): Getting the template for the current action label from a section to another. 582 var temp = sData 583 584 var tempLine = sLine 585 sSet, tempLine, temp = GetNextSetFromData(temp, tempLine, "=") 586 for len(sSet) == 2 && sSet[0] != mSet[0] { 587 sSet, tempLine, temp = GetNextSetFromData(temp, tempLine, "=") 588 } 589 590 sErr = subVerifier(mSet, sSet, mLine, sLine, roomName, filepath, cherryRooms) 591 592 if sErr != nil { 593 return sErr 594 } 595 596 setter(cherryRooms, roomName, mSet, sSet) 597 598 mSet, mLine, mData = GetNextSetFromData(mData, mLine, "=") 599 } 600 return nil 601 } 602 603 func roomActionMainVerifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 604 if cherryRooms.HasAction(roomName, mSet[0]) { 605 return NewCherryFileError(filepath, mLine, "room action \""+mSet[0]+"\" redeclared.") 606 } 607 if len(mSet[1]) == 0 { 608 return NewCherryFileError(filepath, mLine, "unlabeled room action.") 609 } 610 if mSet[1][0] != '"' || mSet[1][len(mSet[1])-1] != '"' { 611 return NewCherryFileError(filepath, mLine, "room action must be set with a valid string.") 612 } 613 return nil 614 } 615 616 func roomActionSubVerifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 617 if sSet[0] != mSet[0] { 618 return NewCherryFileError(filepath, sLine, "there is no template for action \""+mSet[0]+"\".") 619 } 620 if len(sSet[1]) == 0 { 621 return NewCherryFileError(filepath, sLine, "empty room action template.") 622 } 623 if sSet[1][0] != '"' || sSet[1][len(sSet[1])-1] != '"' { 624 return NewCherryFileError(filepath, sLine, "room action template must be set with a valid string.") 625 } 626 var templatePath = sSet[1][1 : len(sSet[1])-1] 627 _, err := ioutil.ReadFile(templatePath) 628 if err != nil { 629 return NewCherryFileError(filepath, sLine, fmt.Sprintf("unable to access file, details: [ %s ]", err.Error())) 630 } 631 return nil 632 } 633 634 func roomActionSetter(cherryRooms *config.CherryRooms, roomName string, mSet, sSet []string) { 635 data, _ := ioutil.ReadFile(sSet[1][1 : len(sSet[1])-1]) 636 cherryRooms.AddAction(roomName, mSet[0], mSet[1][1:len(mSet[1])-1], string(data)) 637 } 638 639 func roomImageMainVerifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 640 if cherryRooms.HasImage(roomName, mSet[0]) { 641 return NewCherryFileError(filepath, mLine, "room image \""+mSet[0]+"\" redeclared.") 642 } 643 if len(mSet[1]) == 0 { 644 return NewCherryFileError(filepath, mLine, "unlabeled room image.") 645 } 646 if mSet[1][0] != '"' || mSet[1][len(mSet[1])-1] != '"' { 647 return NewCherryFileError(filepath, mLine, "room image must be set with a valid string.") 648 } 649 return nil 650 } 651 652 func roomImageSubVerifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 653 if sSet[0] != mSet[0] { 654 return NewCherryFileError(filepath, sLine, "there is no url for image \""+mSet[0]+"\".") 655 } 656 if len(sSet[1]) == 0 { 657 return NewCherryFileError(filepath, sLine, "empty room image url.") 658 } 659 if sSet[1][0] != '"' || sSet[1][len(sSet[1])-1] != '"' { 660 return NewCherryFileError(filepath, sLine, "room image url must be set with a valid string.") 661 } 662 return nil 663 } 664 665 func roomImageSetter(cherryRooms *config.CherryRooms, roomName string, mSet, sSet []string) { 666 // WARN(Santiago): by now we will pass the image template as empty. 667 cherryRooms.AddImage(roomName, mSet[0], mSet[1][1:len(mSet[1])-1], "", sSet[1][1:len(sSet[1])-1]) 668 } 669 670 //func room_sound_main_verifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 671 // if cherryRooms.HasImage(roomName, mSet[0]) { 672 // return NewCherryFileError(filepath, mLine, "room sound \"" + mSet[0] + "\" redeclared.") 673 // } 674 // if len(mSet[1]) == 0 { 675 // return NewCherryFileError(filepath, mLine, "unlabeled room sound.") 676 // } 677 // if mSet[1][0] != '"' || mSet[1][len(mSet[1])-1] != '"' { 678 // return NewCherryFileError(filepath, mLine, "room sound must be set with a valid string.") 679 // } 680 // return nil 681 //} 682 683 //func room_sound_sub_verifier(mSet, sSet []string, mLine, sLine int, roomName, filepath string, cherryRooms *config.CherryRooms) *CherryFileError { 684 // if sSet[0] != mSet[0] { 685 // return NewCherryFileError(filepath, sLine, "there is no url for sound \"" + mSet[0] + "\".") 686 // } 687 // if len(sSet[1]) == 0 { 688 // return NewCherryFileError(filepath, sLine, "empty room sound url.") 689 // } 690 // if sSet[1][0] != '"' || sSet[1][len(sSet[1])-1] != '"' { 691 // return NewCherryFileError(filepath, sLine, "room sound url must be set with a valid string.") 692 // } 693 // return nil 694 //} 695 696 //func room_sound_setter(cherryRooms *config.CherryRooms, roomName string, mSet, sSet []string) { 697 // // WARN(Santiago): by now we will pass the sound template as empty. 698 // cherryRooms.AddSound(roomName, mSet[0], mSet[1][1:len(mSet[1])-1], "", sSet[1][1:len(sSet[1])-1]) 699 //}